CHANGES IN CUPS V1.3.6
+ - Documentation updates (STR #2646, STR #2647, STR #2649)
+ - The PDF filter incorrectly filtered pages when page-ranges
+ and number-up were both specified (STR #2643)
+ - The IPP backend did not handle printing of pictwps files
+ to a non-Mac CUPS server properly.
- The scheduler did not detect network interface changes
on operating systems other than Mac OS X (STR #2631)
- The scheduler now logs the UNIX error message when it
-CHANGES.txt - 2007-12-19
+CHANGES.txt - 2008-01-03
------------------------
CHANGES IN CUPS V1.4b1
+ - Added a new streaming request API (STR #2261)
- Added a new cupsGetNamedDest() function to the CUPS
library for faster printing with lp and lpr (STR #2638)
- The scheduler now sets the PAM RHOST value on systems
-README - CUPS v1.3.0 - 2007-08-13
----------------------------------
+README - CUPS v1.4svn - 2008-01-02
+----------------------------------
Looking for compile instructions? Read the file "INSTALL.txt"
instead...
LEGAL STUFF
- CUPS is Copyright 2007 by Apple Inc. CUPS, the CUPS logo, and
- the Common UNIX Printing System are the trademark property of
- Apple Inc.
+ CUPS is Copyright 2007-2008 by Apple Inc. CUPS, the CUPS logo,
+ and the Common UNIX Printing System are the trademark property
+ of Apple Inc.
The MD5 Digest code is Copyright 1999 Aladdin Enterprises.
*
* IPP backend for the Common UNIX Printing System (CUPS).
*
- * Copyright 2007 by Apple Inc.
+ * Copyright 2007-2008 by Apple Inc.
* Copyright 1997-2007 by Easy Software Products, all rights reserved.
*
* These coded instructions, statements, and computer programs are the
num_options = cupsParseOptions(argv[5], 0, &options);
#ifdef __APPLE__
- if (!strcasecmp(content_type, "application/pictwps") && num_files == 1)
+ if (!strcasecmp(final_content_type, "application/pictwps") &&
+ num_files == 1)
{
if (format_sup != NULL)
{
for (i = 0; i < format_sup->num_values; i ++)
- if (!strcasecmp(content_type, format_sup->values[i].string.text))
+ if (!strcasecmp(final_content_type, format_sup->values[i].string.text))
break;
}
/*
- * "$Id: lpr.c 7017 2007-10-10 22:09:57Z mike $"
+ * "$Id: lpr.c 7170 2008-01-04 02:21:30Z mike $"
*
* "lpr" command for the Common UNIX Printing System (CUPS).
*
*
* Contents:
*
- * main() - Parse options and send files for printing.
- * sighandler() - Signal catcher for when we print from stdin...
+ * main() - Parse options and send files for printing.
*/
/*
#include <cups/cups.h>
#include <cups/i18n.h>
-#ifndef WIN32
-# include <unistd.h>
-# include <signal.h>
-
-
-/*
- * Local functions.
- */
-
-void sighandler(int);
-#endif /* !WIN32 */
-
-
-/*
- * Globals...
- */
-
-char tempfile[1024]; /* Temporary file for printing from stdin */
-
/*
* 'main()' - Parse options and send files for printing.
cups_option_t *options; /* Options */
int deletefile; /* Delete file after print? */
char buffer[8192]; /* Copy buffer */
- ssize_t bytes; /* Bytes copied */
- off_t filesize; /* Size of temp file */
- int temp; /* Temporary file descriptor */
-#if defined(HAVE_SIGACTION) && !defined(HAVE_SIGSET)
- struct sigaction action; /* Signal action */
- struct sigaction oldaction; /* Old signal action */
-#endif /* HAVE_SIGACTION && !HAVE_SIGSET */
_cupsSetLocale(argv);
unlink(files[i]);
}
}
- else
+ else if ((job_id = cupsCreateJob(CUPS_HTTP_DEFAULT, printer,
+ title ? title : "(stdin)",
+ num_options, options)) > 0)
{
- num_files = 1;
-
-#ifndef WIN32
-# if defined(HAVE_SIGSET)
- sigset(SIGHUP, sighandler);
- if (sigset(SIGINT, sighandler) == SIG_IGN)
- sigset(SIGINT, SIG_IGN);
- sigset(SIGTERM, sighandler);
-# elif defined(HAVE_SIGACTION)
- memset(&action, 0, sizeof(action));
- action.sa_handler = sighandler;
-
- sigaction(SIGHUP, &action, NULL);
- sigaction(SIGINT, NULL, &oldaction);
- if (oldaction.sa_handler != SIG_IGN)
- sigaction(SIGINT, &action, NULL);
- sigaction(SIGTERM, &action, NULL);
-# else
- signal(SIGHUP, sighandler);
- if (signal(SIGINT, sighandler) == SIG_IGN)
- signal(SIGINT, SIG_IGN);
- signal(SIGTERM, sighandler);
-# endif
-#endif /* !WIN32 */
-
- if ((temp = cupsTempFd(tempfile, sizeof(tempfile))) < 0)
- {
- _cupsLangPrintf(stderr,
- _("%s: Error - unable to create temporary file "
- "\"%s\" - %s\n"),
- argv[0], tempfile, strerror(errno));
- return (1);
- }
+ http_status_t status; /* Write status */
+ const char *format; /* Document format */
+ ssize_t bytes; /* Bytes read */
- while ((bytes = read(0, buffer, sizeof(buffer))) > 0)
- if (write(temp, buffer, bytes) < 0)
- {
- _cupsLangPrintf(stderr,
- _("%s: Error - unable to write to temporary file "
- "\"%s\" - %s\n"),
- argv[0], tempfile, strerror(errno));
- close(temp);
- unlink(tempfile);
- return (1);
- }
- filesize = lseek(temp, 0, SEEK_CUR);
- close(temp);
+ if (cupsGetOption("raw", num_options, options))
+ format = CUPS_FORMAT_RAW;
+ else if ((format = cupsGetOption("document-format", num_options,
+ options)) == NULL)
+ format = CUPS_FORMAT_AUTO;
+
+ status = cupsStartDocument(CUPS_HTTP_DEFAULT, printer, job_id, NULL,
+ format, 1);
- if (filesize <= 0)
+ while (status == HTTP_CONTINUE &&
+ (bytes = read(0, buffer, sizeof(buffer))) > 0)
+ status = cupsWriteRequestData(CUPS_HTTP_DEFAULT, buffer, bytes);
+
+ if (status != HTTP_CONTINUE)
{
_cupsLangPrintf(stderr,
- _("%s: Error - stdin is empty, so no job has been sent.\n"),
- argv[0]);
- unlink(tempfile);
+ _("%s: Error - unable to queue from stdin - %s\n"),
+ argv[0], httpStatus(status));
return (1);
}
- if (title)
- job_id = cupsPrintFile(printer, tempfile, title, num_options, options);
- else
- job_id = cupsPrintFile(printer, tempfile, "(stdin)", num_options, options);
-
- unlink(tempfile);
+ if (cupsFinishDocument(CUPS_HTTP_DEFAULT, printer) != IPP_OK)
+ job_id = 0;
}
if (job_id < 1)
}
-#ifndef WIN32
-/*
- * 'sighandler()' - Signal catcher for when we print from stdin...
- */
-
-void
-sighandler(int s) /* I - Signal number */
-{
- /*
- * Remove the temporary file we're using to print from stdin...
- */
-
- unlink(tempfile);
-
- /*
- * Exit...
- */
-
- exit(s);
-}
-#endif /* !WIN32 */
-
-
/*
- * End of "$Id: lpr.c 7017 2007-10-10 22:09:57Z mike $".
+ * End of "$Id: lpr.c 7170 2008-01-04 02:21:30Z mike $".
*/
* Constants...
*/
-# define CUPS_VERSION 1.0400
+# define CUPS_VERSION 1.0399
# define CUPS_VERSION_MAJOR 1
# define CUPS_VERSION_MINOR 4
-# define CUPS_VERSION_PATCH 0
-# define CUPS_DATE_ANY -1
+# define CUPS_VERSION_PATCH -1
+
+# define CUPS_DATE_ANY (time_t)-1
+# define CUPS_FORMAT_AUTO "application/octet-stream"
+# define CUPS_FORMAT_PDF "application/pdf"
+# define CUPS_FORMAT_POSTSCRIPT "application/postscript"
+# define CUPS_FORMAT_RAW "application/vnd.cups-raw"
+# define CUPS_FORMAT_TEXT "text/plain"
+# define CUPS_HTTP_DEFAULT (http_t *)0
+# define CUPS_LENGTH_VARIABLE (ssize_t)0
/*
* Functions...
*/
-extern int cupsCancelJob(const char *printer, int job);
+extern int cupsCancelJob(const char *name, int job_id);
extern ipp_t *cupsDoFileRequest(http_t *http, ipp_t *request,
const char *resource,
const char *filename);
extern const char *cupsGetDefault(void);
extern int cupsGetJobs(cups_job_t **jobs, const char *dest,
int myjobs, int completed);
-extern const char *cupsGetPPD(const char *printer);
+extern const char *cupsGetPPD(const char *name);
extern int cupsGetPrinters(char ***printers) _CUPS_DEPRECATED;
extern ipp_status_t cupsLastError(void);
-extern int cupsPrintFile(const char *printer, const char *filename,
+extern int cupsPrintFile(const char *name, const char *filename,
const char *title, int num_options,
cups_option_t *options);
-extern int cupsPrintFiles(const char *printer, int num_files,
+extern int cupsPrintFiles(const char *name, int num_files,
const char **files, const char *title,
int num_options, cups_option_t *options);
extern char *cupsTempFile(char *filename, int len) _CUPS_DEPRECATED;
extern const char *cupsGetDefault2(http_t *http) _CUPS_API_1_1_21;
extern int cupsGetDests2(http_t *http, cups_dest_t **dests) _CUPS_API_1_1_21;
extern int cupsGetJobs2(http_t *http, cups_job_t **jobs,
- const char *dest, int myjobs,
+ const char *name, int myjobs,
int completed) _CUPS_API_1_1_21;
-extern const char *cupsGetPPD2(http_t *http, const char *printer) _CUPS_API_1_1_21;
-extern int cupsPrintFile2(http_t *http, const char *printer,
+extern const char *cupsGetPPD2(http_t *http, const char *name) _CUPS_API_1_1_21;
+extern int cupsPrintFile2(http_t *http, const char *name,
const char *filename,
const char *title, int num_options,
cups_option_t *options) _CUPS_API_1_1_21;
-extern int cupsPrintFiles2(http_t *http, const char *printer,
+extern int cupsPrintFiles2(http_t *http, const char *name,
int num_files, const char **files,
const char *title, int num_options,
cups_option_t *options) _CUPS_API_1_1_21;
cups_dest_t *dests) _CUPS_API_1_3;
/**** New in CUPS 1.4 ****/
+extern ipp_status_t cupsCancelJob2(http_t *http, int job_id, int purge);
+extern int cupsCreateJob(http_t *http, const char *name,
+ const char *title, int num_options,
+ cups_option_t *options) _CUPS_API_1_4;
+extern ipp_status_t cupsFinishDocument(http_t *http,
+ const char *name) _CUPS_API_1_4;
extern cups_dest_t *cupsGetNamedDest(http_t *http, const char *name,
const char *instance) _CUPS_API_1_4;
extern http_status_t cupsGetPPD3(http_t *http, const char *name,
time_t *modtime, char *buffer,
size_t bufsize) _CUPS_API_1_4;
+extern ipp_t *cupsGetResponse(http_t *http,
+ const char *resource) _CUPS_API_1_4;
+extern ssize_t cupsReadResponseData(http_t *http, char *buffer,
+ size_t length) _CUPS_API_1_4;
+extern http_status_t cupsSendRequest(http_t *http, ipp_t *request,
+ const char *resource,
+ size_t length) _CUPS_API_1_4;
+extern http_status_t cupsStartDocument(http_t *http, const char *name,
+ int job_id, const char *docname,
+ const char *format,
+ int last_document) _CUPS_API_1_4;
+extern http_status_t cupsWriteRequestData(http_t *http, const char *buffer,
+ size_t length) _CUPS_API_1_4;
# ifdef __cplusplus
}
int /* O - Number of destinations */
cupsGetDests(cups_dest_t **dests) /* O - Destinations */
{
- int num_dests; /* Number of destinations */
- _cups_globals_t *cg = _cupsGlobals(); /* Pointer to library globals */
-
-
- /*
- * Connect to the CUPS server and get the destination list and options...
- */
-
- if (!cg->http)
- cg->http = httpConnectEncrypt(cupsServer(), ippPort(), cupsEncryption());
-
- num_dests = cupsGetDests2(cg->http, dests);
-
- return (num_dests);
+ return (cupsGetDests2(CUPS_HTTP_DEFAULT, dests));
}
*/
int /* O - Number of destinations */
-cupsGetDests2(http_t *http, /* I - HTTP connection */
+cupsGetDests2(http_t *http, /* I - HTTP connection or CUPS_HTTP_DEFAULT */
cups_dest_t **dests) /* O - Destinations */
{
int i; /* Looping var */
*instance; /* Pointer to instance name */
int num_reals; /* Number of real queues */
cups_dest_t *reals; /* Real queues */
- _cups_globals_t *cg = _cupsGlobals(); /* Global data */
+ _cups_globals_t *cg = _cupsGlobals(); /* Pointer to library globals */
/*
* Range check the input...
*/
- if (!http || !dests)
+ if (!dests)
return (0);
/*
* If NULL is returned, the destination does not exist or there is no default
* destination.
*
- * If "http" is NULL, the connection to the default print server will be used.
+ * If "http" is CUPS_HTTP_DEFAULT, the connection to the default print server
+ * will be used.
*
* If "name" is NULL, the default printer for the current user will be returned.
*
*/
cups_dest_t * /* O - Destination or NULL */
-cupsGetNamedDest(http_t *http, /* I - HTTP connection or NULL */
+cupsGetNamedDest(http_t *http, /* I - HTTP connection or CUPS_HTTP_DEFAULT */
const char *name, /* I - Destination name or NULL */
const char *instance) /* I - Instance name or NULL */
{
_cups_globals_t *cg = _cupsGlobals(); /* Pointer to library globals */
- /*
- * Connect to the server as needed...
- */
-
- if (!http)
- {
- if (!cg->http &&
- (cg->http = httpConnectEncrypt(cupsServer(), ippPort(),
- cupsEncryption())) == NULL)
- return (NULL);
-
- http = cg->http;
- }
-
/*
* If "name" is NULL, find the default destination...
*/
/*
- * 'cupsDestSetDefaultDest()' - Set the default destination.
+ * 'cupsSetDefaultDest()' - Set the default destination.
*
* @since CUPS 1.3@
*/
cupsSetDests(int num_dests, /* I - Number of destinations */
cups_dest_t *dests) /* I - Destinations */
{
- _cups_globals_t *cg = _cupsGlobals(); /* Pointer to library globals */
-
-
- /*
- * Connect to the CUPS server and save the destination list and options...
- */
-
- if (!cg->http)
- cg->http = httpConnectEncrypt(cupsServer(), ippPort(), cupsEncryption());
-
- cupsSetDests2(cg->http, num_dests, dests);
+ cupsSetDests2(CUPS_HTTP_DEFAULT, num_dests, dests);
}
*/
int /* O - 0 on success, -1 on error */
-cupsSetDests2(http_t *http, /* I - HTTP connection */
+cupsSetDests2(http_t *http, /* I - HTTP connection or CUPS_HTTP_DEFAULT */
int num_dests, /* I - Number of destinations */
cups_dest_t *dests) /* I - Destinations */
{
cups_dest_t *temps, /* Temporary destinations */
*temp; /* Current temporary dest */
const char *val; /* Value of temporary option */
- _cups_globals_t *cg = _cupsGlobals(); /* Global data */
+ _cups_globals_t *cg = _cupsGlobals(); /* Pointer to library globals */
/*
* Range check the input...
*/
- if (!http || !num_dests || !dests)
+ if (!num_dests || !dests)
return (-1);
/*
*/
static int /* O - Number of destinations */
-cups_get_sdests(http_t *http, /* I - HTTP connection */
+cups_get_sdests(http_t *http, /* I - HTTP connection or CUPS_HTTP_DEFAULT */
ipp_op_t op, /* I - IPP operation */
const char *name, /* I - Name of destination */
int num_dests, /* I - Number of destinations */
* Prototypes...
*/
+extern http_t *_cupsConnect(void);
extern const char *_cupsGetPassword(const char *prompt);
extern _cups_globals_t *_cupsGlobals(void);
extern void _cupsSetError(ipp_status_t status, const char *message);
_cupsBackChannelWrite
_cupsBackendDeviceURI
_cupsCancelJob
+_cupsCancelJob2
_cupsCharsetToUTF8
+_cupsCreateJob
_cupsDirClose
_cupsDirOpen
_cupsDirRead
_cupsFileTell
_cupsFileUnlock
_cupsFileWrite
+_cupsFinishDocument
_cupsFreeDests
_cupsFreeJobs
_cupsFreeOptions
_cupsGetPPD2
_cupsGetPPD3
_cupsGetPrinters
+_cupsGetResponse
_cupsGetServerPPD
_cupsLangDefault
_cupsLangEncoding
_cupsPrintFiles2
_cupsPutFd
_cupsPutFile
+_cupsReadResponseData
_cupsRemoveDest
_cupsRemoveOption
+_cupsSendRequest
_cupsServer
_cupsSetDefaultDest
_cupsSetDests
_cupsSideChannelDoRequest
_cupsSideChannelRead
_cupsSideChannelWrite
+_cupsStartDocument
_cupsTempFd
_cupsTempFile
_cupsTempFile2
_cupsUTF32ToUTF8
_cupsUTF8ToCharset
_cupsUTF8ToUTF32
+_cupsWriteRequestData
_httpAddrAny
_httpAddrConnect
_httpAddrEqual
*
* IPP utilities for the Common UNIX Printing System (CUPS).
*
- * Copyright 2007 by Apple Inc.
+ * Copyright 2007-2008 by Apple Inc.
* Copyright 1997-2007 by Easy Software Products.
*
* These coded instructions, statements, and computer programs are the
*
* Contents:
*
- * cupsDoFileRequest() - Do an IPP request with a file.
- * cupsDoIORequest() - Do an IPP request with file descriptors.
- * cupsDoRequest() - Do an IPP request.
- * _cupsSetError() - Set the last IPP status code and status-message.
- * _cupsSetHTTPError() - Set the last error using the HTTP status.
+ * cupsDoFileRequest() - Do an IPP request with a file.
+ * cupsDoIORequest() - Do an IPP request with file descriptors.
+ * cupsDoRequest() - Do an IPP request.
+ * cupsGetResponse() - Get a response to an IPP request.
+ * cupsReadResponseData() - Read additional data after the IPP response.
+ * cupsSendRequest() - Send an IPP request.
+ * cupsWriteRequestData() - Write additional data after an IPP request.
+ * _cupsSetError() - Set the last IPP status code and status-message.
+ * _cupsSetHTTPError() - Set the last error using the HTTP status.
*/
/*
*/
ipp_t * /* O - Response data */
-cupsDoFileRequest(http_t *http, /* I - HTTP connection to server */
+cupsDoFileRequest(http_t *http, /* I - HTTP connection or CUPS_HTTP_DEFAULT */
ipp_t *request, /* I - IPP request */
const char *resource, /* I - HTTP resource for POST */
const char *filename) /* I - File to send or NULL for none */
*/
ipp_t * /* O - Response data */
-cupsDoIORequest(http_t *http, /* I - HTTP connection to server */
+cupsDoIORequest(http_t *http, /* I - HTTP connection or CUPS_HTTP_DEFAULT */
ipp_t *request, /* I - IPP request */
const char *resource, /* I - HTTP resource for POST */
int infile, /* I - File to read from or -1 for none */
int outfile) /* I - File to write to or -1 for none */
{
- ipp_t *response; /* IPP response data */
- size_t length; /* Content-Length value */
+ ipp_t *response = NULL; /* IPP response data */
+ size_t length = 0; /* Content-Length value */
http_status_t status; /* Status of HTTP request */
- int got_status; /* Did we get the status? */
- ipp_state_t state; /* State of IPP processing */
struct stat fileinfo; /* File information */
int bytes; /* Number of bytes read/written */
char buffer[32768]; /* Output buffer */
- http_status_t expect; /* Expect: header to use */
- DEBUG_printf(("cupsDoFileRequest(%p, %p, \'%s\', \'%s\')\n",
- http, request, resource ? resource : "(null)",
- filename ? filename : "(null)"));
+ DEBUG_printf(("cupsDoIORequest(http=%p, request=%p, resource=\"%s\""
+ "infile=%d, outfile=%d)\n", http, request,
+ resource ? resource : "(null)", infile, outfile));
+
+ /*
+ * Range check input...
+ */
- if (http == NULL || request == NULL || resource == NULL)
+ if (!request || !resource)
{
- if (request != NULL)
- ippDelete(request);
+ ippDelete(request);
- _cupsSetError(IPP_INTERNAL_ERROR, NULL);
+ _cupsSetError(IPP_INTERNAL_ERROR, strerror(EINVAL));
return (NULL);
}
+ /*
+ * Get the default connection as needed...
+ */
+
+ if (!http)
+ http = _cupsConnect();
+
/*
* See if we have a file to send...
*/
* Can't get file information!
*/
- _cupsSetError(errno == ENOENT ? IPP_NOT_FOUND : IPP_NOT_AUTHORIZED,
+ _cupsSetError(errno == EBADF ? IPP_NOT_FOUND : IPP_NOT_AUTHORIZED,
strerror(errno));
ippDelete(request);
return (NULL);
}
+
+#ifndef WIN32
+ if (!S_ISREG(fileinfo.st_mode))
+ length = 0; /* Chunk when piping */
+ else
+#endif /* !WIN32 */
+ length = ippLength(request) + fileinfo.st_size;
+ }
+ else
+ length = ippLength(request);
+
+ /*
+ * Loop until we can send the request without authorization problems.
+ */
+
+ while (response == NULL)
+ {
+ DEBUG_puts("cupsDoFileRequest: setup...");
+
+ /*
+ * Send the request...
+ */
+
+ status = cupsSendRequest(http, request, resource, length);
+
+ DEBUG_printf(("cupsDoFileRequest: status=%d\n", status));
+
+ if (status == HTTP_CONTINUE && request->state == IPP_DATA && infile >= 0)
+ {
+ DEBUG_puts("cupsDoFileRequest: file write...");
+
+ /*
+ * Send the file with the request...
+ */
+
+#ifndef WIN32
+ if (S_ISREG(fileinfo.st_mode))
+#endif /* WIN32 */
+ lseek(infile, 0, SEEK_SET);
+
+ while ((bytes = (int)read(infile, buffer, sizeof(buffer))) > 0)
+ {
+ if (httpCheck(http))
+ {
+ if ((status = httpUpdate(http)) != HTTP_CONTINUE)
+ break;
+ }
+
+ if (httpWrite2(http, buffer, bytes) < bytes)
+ break;
+ }
+ }
+
+ /*
+ * Get the server's response...
+ */
+
+ if (status == HTTP_CONTINUE || status == HTTP_OK)
+ {
+ response = cupsGetResponse(http, resource);
+ status = http->status;
+ }
+
+ if (response)
+ {
+ if (outfile >= 0)
+ {
+ /*
+ * Write trailing data to file...
+ */
+
+ while ((bytes = (int)httpRead2(http, buffer, sizeof(buffer))) > 0)
+ if (write(outfile, buffer, bytes) < bytes)
+ break;
+ }
+ else
+ {
+ /*
+ * Flush any remaining data...
+ */
+
+ httpFlush(http);
+ }
+ }
+ }
+
+ /*
+ * Delete the original request and return the response...
+ */
+
+ ippDelete(request);
+
+ return (response);
+}
+
+
+/*
+ * 'cupsDoRequest()' - Do an IPP request.
+ *
+ * This function sends the IPP request to the specified server, retrying
+ * and authenticating as necessary. The request is freed with ippDelete()
+ * after receiving a valid IPP response.
+ */
+
+ipp_t * /* O - Response data */
+cupsDoRequest(http_t *http, /* I - HTTP connection or CUPS_HTTP_DEFAULT */
+ ipp_t *request, /* I - IPP request */
+ const char *resource) /* I - HTTP resource for POST */
+{
+ return (cupsDoFileRequest(http, request, resource, NULL));
+}
+
+
+/*
+ * 'cupsGetResponse()' - Get a response to an IPP request.
+ *
+ * Use this function to get the response for an IPP request sent using
+ * cupsSendDocument() or cupsSendRequest(). For requests that return
+ * additional data, use httpRead() after getting a successful response.
+ *
+ * @since CUPS 1.4@
+ */
+
+ipp_t * /* O - Response or NULL on HTTP error */
+cupsGetResponse(http_t *http, /* I - HTTP connection or CUPS_HTTP_DEFAULT */
+ const char *resource) /* I - HTTP resource for POST */
+{
+ http_status_t status; /* HTTP status */
+ ipp_state_t state; /* IPP read state */
+ ipp_t *response = NULL; /* IPP response */
+
+
+ DEBUG_printf(("cupsGetReponse(http=%p)\n", http));
+
+ /*
+ * Connect to the default server as needed...
+ */
+
+ if (!http)
+ http = _cupsConnect();
+
+ if (!http || (http->state != HTTP_POST_RECV && http->state != HTTP_POST_SEND))
+ return (NULL);
+
+ /*
+ * Check for an unfinished chunked request...
+ */
+
+ if (http->data_encoding == HTTP_ENCODE_CHUNKED)
+ {
+ /*
+ * Send a 0-length chunk to finish off the request...
+ */
+
+ DEBUG_puts("cupsGetResponse: Finishing chunked POST...");
+
+ if (httpWrite2(http, "", 0) < 0)
+ return (NULL);
+ }
+
+ /*
+ * Wait for a response from the server...
+ */
+
+ DEBUG_puts("cupsGetResponse: update...");
+
+ while ((status = httpUpdate(http)) == HTTP_CONTINUE)
+ /* Do nothing but update */;
+
+ DEBUG_printf(("cupsGetResponse: status = %d\n", status));
+
+ if (status == HTTP_OK)
+ {
+ /*
+ * Get the IPP response...
+ */
+
+ response = ippNew();
+
+ while ((state = ippRead(http, response)) != IPP_DATA)
+ if (state == IPP_ERROR)
+ break;
+
+ if (state == IPP_ERROR)
+ {
+ /*
+ * Delete the response...
+ */
+
+ DEBUG_puts("IPP read error!");
+
+ ippDelete(response);
+ response = NULL;
+
+ _cupsSetError(IPP_SERVICE_UNAVAILABLE, strerror(errno));
+ }
+ }
+ else if (status != HTTP_ERROR)
+ {
+ /*
+ * Flush any error message...
+ */
+
+ httpFlush(http);
+
+ /*
+ * Then handle encryption and authentication...
+ */
+
+ if (status == HTTP_UNAUTHORIZED)
+ {
+ /*
+ * See if we can do authentication...
+ */
+
+ DEBUG_puts("cupsGetResponse: Need authorization...");
+
+ if (!cupsDoAuthentication(http, "POST", resource))
+ httpReconnect(http);
+ }
+
+#ifdef HAVE_SSL
+ else if (status == HTTP_UPGRADE_REQUIRED)
+ {
+ /*
+ * Force a reconnect with encryption...
+ */
+
+ DEBUG_puts("cupsGetResponse: Need encryption...");
+
+ if (!httpReconnect(http))
+ httpEncryption(http, HTTP_ENCRYPT_REQUIRED);
+ }
+#endif /* HAVE_SSL */
+ }
+
+ if (response)
+ {
+ ipp_attribute_t *attr; /* status-message attribute */
+
+
+ attr = ippFindAttribute(response, "status-message", IPP_TAG_TEXT);
+
+ _cupsSetError(response->request.status.status_code,
+ attr ? attr->values[0].string.text :
+ ippErrorString(response->request.status.status_code));
+ }
+ else if (status != HTTP_OK)
+ _cupsSetHTTPError(status);
+
+ return (response);
+}
+
+
+/*
+ * 'cupsReadResponseData()' - Read additional data after the IPP response.
+ *
+ * This function is used after cupsGetResponse() to read the PPD or document
+ * files for CUPS_GET_PPD and CUPS_GET_DOCUMENT requests, respectively.
+ *
+ * @since CUPS 1.4@
+ */
+
+ssize_t /* O - Bytes read, 0 on EOF, -1 on error */
+cupsReadResponseData(
+ http_t *http, /* I - HTTP connection or CUPS_HTTP_DEFAULT */
+ char *buffer, /* I - Buffer to use */
+ size_t length) /* I - Number of bytes to read */
+{
+ /*
+ * Get the default connection as needed...
+ */
+
+ if (!http)
+ {
+ _cups_globals_t *cg = _cupsGlobals();
+ /* Pointer to library globals */
+
+ if ((http = cg->http) == NULL)
+ {
+ _cupsSetError(IPP_INTERNAL_ERROR, "No active connection");
+ return (-1);
+ }
}
+ /*
+ * Then read from the HTTP connection...
+ */
+
+ return (httpRead2(http, buffer, length));
+}
+
+
+/*
+ * 'cupsSendRequest()' - Send an IPP request.
+ *
+ * Use httpWrite() to write any additional data (document, PPD file, etc.)
+ * for the request, cupsGetResponse() to get the IPP response, and httpRead()
+ * to read any additional data following the response. Only one request can be
+ * sent/queued at a time.
+ *
+ * Unlike cupsDoFileRequest(), cupsDoIORequest(), and cupsDoRequest(), the
+ * request is not freed.
+ *
+ * @since CUPS 1.4@
+ */
+
+http_status_t /* O - Initial HTTP status */
+cupsSendRequest(http_t *http, /* I - HTTP connection or CUPS_HTTP_DEFAULT */
+ ipp_t *request, /* I - IPP request */
+ const char *resource, /* I - Resource path */
+ size_t length) /* I - Length of data to follow or CUPS_LENGTH_VARIABLE */
+{
+ http_status_t status; /* Status of HTTP request */
+ int got_status; /* Did we get the status? */
+ ipp_state_t state; /* State of IPP processing */
+ http_status_t expect; /* Expect: header to use */
+
+
+ DEBUG_printf(("cupsSendRequest(http=%p, request=%p, resource=\"%s\", "
+ "length=" CUPS_LLFMT ")\n", http, request,
+ resource ? resource : "(null)", CUPS_LLCAST length));
+
+ /*
+ * Range check input...
+ */
+
+ if (!request || !resource)
+ {
+ _cupsSetError(IPP_INTERNAL_ERROR, strerror(EINVAL));
+
+ return (HTTP_ERROR);
+ }
+
+ /*
+ * Get the default connection as needed...
+ */
+
+ if (!http)
+ http = _cupsConnect();
+
#ifdef HAVE_SSL
/*
* See if we have an auth-info attribute and are communicating over
if (ippFindAttribute(request, "auth-info", IPP_TAG_TEXT) &&
!httpAddrLocalhost(http->hostaddr) && !http->tls &&
httpEncryption(http, HTTP_ENCRYPT_REQUIRED))
- return (NULL);
+ return (HTTP_ERROR);
#endif /* HAVE_SSL */
/*
* Loop until we can send the request without authorization problems.
*/
- response = NULL;
- status = HTTP_ERROR;
- expect = HTTP_CONTINUE;
+ status = HTTP_ERROR;
+ expect = HTTP_CONTINUE;
- while (response == NULL)
+ for (;;)
{
- DEBUG_puts("cupsDoFileRequest: setup...");
+ DEBUG_puts("cupsSendRequest: setup...");
/*
* Setup the HTTP variables needed...
*/
- length = ippLength(request);
- if (infile >= 0)
- {
-#ifndef WIN32
- if (!S_ISREG(fileinfo.st_mode))
- length = 0; /* Chunk when piping */
- else
-#endif /* !WIN32 */
- length += fileinfo.st_size;
- }
-
httpClearFields(http);
httpSetLength(http, length);
httpSetField(http, HTTP_FIELD_CONTENT_TYPE, "application/ipp");
httpSetField(http, HTTP_FIELD_AUTHORIZATION, http->authstring);
httpSetExpect(http, expect);
- DEBUG_printf(("cupsDoFileRequest: authstring=\"%s\"\n", http->authstring));
+ DEBUG_printf(("cupsSendRequest: authstring=\"%s\"\n", http->authstring));
/*
* Try the request...
*/
- DEBUG_puts("cupsDoFileRequest: post...");
+ DEBUG_puts("cupsSendRequest: post...");
if (httpPost(http, resource))
{
if (httpReconnect(http))
- {
- status = HTTP_ERROR;
- break;
- }
+ return (HTTP_ERROR);
else
continue;
}
* Send the IPP data...
*/
- DEBUG_puts("cupsDoFileRequest: ipp write...");
+ DEBUG_puts("cupsSendRequest: ipp write...");
request->state = IPP_IDLE;
status = HTTP_CONTINUE;
break;
}
- if (!got_status)
- {
- /*
- * Wait up to 1 second to get the 100-continue response...
- */
+ /*
+ * Wait up to 1 second to get the 100-continue response as needed...
+ */
+ if (!got_status && expect == HTTP_CONTINUE)
+ {
if (httpWait(http, 1000))
status = httpUpdate(http);
}
else if (httpCheck(http))
status = httpUpdate(http);
- if (status == HTTP_CONTINUE && state == IPP_DATA && infile >= 0)
- {
- DEBUG_puts("cupsDoFileRequest: file write...");
-
- /*
- * Send the file...
- */
-
-#ifndef WIN32
- if (S_ISREG(fileinfo.st_mode))
-#endif /* WIN32 */
- lseek(infile, 0, SEEK_SET);
-
- while ((bytes = (int)read(infile, buffer, sizeof(buffer))) > 0)
- {
- if (httpCheck(http))
- {
- if ((status = httpUpdate(http)) != HTTP_CONTINUE)
- break;
- }
-
- if (httpWrite2(http, buffer, bytes) < bytes)
- break;
- }
- }
-
/*
- * Get the server's return status...
+ * Process the current HTTP status...
*/
- DEBUG_puts("cupsDoFileRequest: update...");
-
- while (status == HTTP_CONTINUE)
- status = httpUpdate(http);
-
- DEBUG_printf(("cupsDoFileRequest: status = %d\n", status));
-
- if (status == HTTP_UNAUTHORIZED)
+ switch (status)
{
- DEBUG_puts("cupsDoFileRequest: unauthorized...");
-
- /*
- * Flush any error message...
- */
-
- httpFlush(http);
-
- /*
- * See if we can do authentication...
- */
-
- if (cupsDoAuthentication(http, "POST", resource))
- break;
+ case HTTP_ERROR :
+ case HTTP_CONTINUE :
+ case HTTP_OK :
+ return (status);
- if (httpReconnect(http))
- {
- status = HTTP_ERROR;
- break;
- }
+ case HTTP_UNAUTHORIZED :
+ if (!cupsDoAuthentication(http, "POST", resource))
+ if (httpReconnect(http))
+ return (HTTP_ERROR);
- continue;
- }
- else if (status == HTTP_ERROR)
- {
- DEBUG_printf(("cupsDoFileRequest: http->error=%d (%s)\n", http->error,
- strerror(http->error)));
+ return (status);
-#ifdef WIN32
- if (http->error != WSAENETDOWN && http->error != WSAENETUNREACH &&
- http->error != WSAETIMEDOUT)
-#else
- if (http->error != ENETDOWN && http->error != ENETUNREACH &&
- http->error != ETIMEDOUT)
-#endif /* WIN32 */
- continue;
- else
- break;
- }
#ifdef HAVE_SSL
- else if (status == HTTP_UPGRADE_REQUIRED)
- {
- /* Flush any error message... */
- httpFlush(http);
+ case HTTP_UPGRADE_REQUIRED :
+ /*
+ * Flush any error message, reconnect, and then upgrade with
+ * encryption...
+ */
- /* Reconnect... */
- if (httpReconnect(http))
- {
- status = HTTP_ERROR;
- break;
- }
+ if (httpReconnect(http))
+ return (HTTP_ERROR);
- /* Upgrade with encryption... */
- httpEncryption(http, HTTP_ENCRYPT_REQUIRED);
+ httpEncryption(http, HTTP_ENCRYPT_REQUIRED);
- /* Try again, this time with encryption enabled... */
- continue;
- }
+ return (status);
#endif /* HAVE_SSL */
- else if (status == HTTP_EXPECTATION_FAILED)
- {
- /*
- * Don't try using the Expect: header the next time around...
- */
- expect = (http_status_t)0;
- }
- else if (status != HTTP_OK)
- {
- DEBUG_printf(("cupsDoFileRequest: error %d...\n", status));
+ case HTTP_EXPECTATION_FAILED :
+ /*
+ * Don't try using the Expect: header the next time around...
+ */
- /*
- * Flush any error message...
- */
+ expect = (http_status_t)0;
- httpFlush(http);
- break;
- }
- else
- {
- /*
- * Read the response...
- */
-
- DEBUG_puts("cupsDoFileRequest: response...");
-
- response = ippNew();
-
- while ((state = ippRead(http, response)) != IPP_DATA)
- if (state == IPP_ERROR)
- break;
-
- if (state == IPP_ERROR)
- {
- /*
- * Delete the response...
- */
-
- DEBUG_puts("IPP read error!");
- ippDelete(response);
- response = NULL;
-
- _cupsSetError(IPP_SERVICE_UNAVAILABLE, strerror(errno));
-
- break;
- }
- else if (outfile >= 0)
- {
- /*
- * Write trailing data to file...
- */
-
- while ((bytes = (int)httpRead2(http, buffer, sizeof(buffer))) > 0)
- if (write(outfile, buffer, bytes) < bytes)
- break;
- }
- else
- {
- /*
- * Flush any remaining data...
- */
+ default :
+ /*
+ * Some other error...
+ */
- httpFlush(http);
- }
+ return (status);
}
}
+}
+
+
+/*
+ * 'cupsWriteRequestData()' - Write additional data after an IPP request.
+ *
+ * This function is used after cupsSendRequest() or cupsStartDocument()
+ * to provide a PPD or document file as needed.
+ *
+ * @since CUPS 1.4@
+ */
+http_status_t /* O - HTTP_CONTINUE if OK or HTTP status on error */
+cupsWriteRequestData(
+ http_t *http, /* I - HTTP connection or CUPS_HTTP_DEFAULT */
+ const char *buffer, /* I - Bytes to write */
+ size_t length) /* I - Number of bytes to write */
+{
/*
- * Delete the original request and return the response...
+ * Get the default connection as needed...
*/
-
- ippDelete(request);
- if (response)
+ if (!http)
{
- ipp_attribute_t *attr; /* status-message attribute */
-
+ _cups_globals_t *cg = _cupsGlobals();
+ /* Pointer to library globals */
- attr = ippFindAttribute(response, "status-message", IPP_TAG_TEXT);
-
- _cupsSetError(response->request.status.status_code,
- attr ? attr->values[0].string.text :
- ippErrorString(response->request.status.status_code));
+ if ((http = cg->http) == NULL)
+ {
+ _cupsSetError(IPP_INTERNAL_ERROR, "No active connection");
+ return (HTTP_ERROR);
+ }
}
- else if (status != HTTP_OK)
- _cupsSetHTTPError(status);
- return (response);
-}
+ /*
+ * Then write to the HTTP connection...
+ */
+ if (httpWrite2(http, buffer, length) < 0)
+ return (HTTP_ERROR);
-/*
- * 'cupsDoRequest()' - Do an IPP request.
- *
- * This function sends the IPP request to the specified server, retrying
- * and authenticating as necessary. The request is freed with ippDelete()
- * after receiving a valid IPP response.
- */
+ /*
+ * Finally, check if we have any pending data from the server...
+ */
-ipp_t * /* O - Response data */
-cupsDoRequest(http_t *http, /* I - HTTP connection to server */
- ipp_t *request, /* I - IPP request */
- const char *resource) /* I - HTTP resource for POST */
-{
- return (cupsDoFileRequest(http, request, resource, NULL));
+ if (httpCheck(http))
+ return (httpUpdate(http));
+ else
+ return (HTTP_CONTINUE);
}
*
* Printing utilities for the Common UNIX Printing System (CUPS).
*
- * Copyright 2007 by Apple Inc.
+ * Copyright 2007-2008 by Apple Inc.
* Copyright 1997-2006 by Easy Software Products.
*
* These coded instructions, statements, and computer programs are the
* 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 from the default
+ * cupsGetDefault() - Get the default printer or class for the default
+ * server.
+ * cupsGetDefault2() - Get the default printer or class for the specified
* server.
- * cupsGetDefault2() - Get the default printer or class from 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 on the specified
+ * 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.
* the default server.
* cupsPrintFiles2() - Print one or more files to a printer or class on
* the specified server.
- * cups_connect() - Connect to the specified host...
+ * 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.
*/
* Local functions...
*/
-static char *cups_connect(const char *name, char *printer, char *hostname);
static int cups_get_printer_uri(http_t *http, const char *name,
char *host, int hostsize, int *port,
char *resource, int resourcesize,
int /* O - 1 on success, 0 on failure */
cupsCancelJob(const char *name, /* I - Name of printer or class */
- int job) /* I - Job ID */
+ int job_id) /* I - Job ID */
{
- char printer[HTTP_MAX_URI], /* Printer name */
- hostname[HTTP_MAX_URI], /* Hostname */
- uri[HTTP_MAX_URI]; /* Printer URI */
- ipp_t *request, /* IPP request */
- *response; /* IPP response */
- _cups_globals_t *cg = _cupsGlobals(); /* Pointer to library globals */
+ return (cupsCancelJob2(CUPS_HTTP_DEFAULT, job_id, 0)
+ < IPP_REDIRECTION_OTHER_SITE);
+}
+
+
+/*
+ * 'cupsCancelJob2()' - Cancel or purge a print job.
+ *
+ * Canceled jobs remain in the job history while purged jobs are removed
+ * from the job history.
+ *
+ * Use the cupsLastError() and cupsLastErrorString() functions to get
+ * the cause of any failure.
+ *
+ * @since CUPS 1.4@
+ */
+
+ipp_status_t /* O - IPP status */
+cupsCancelJob2(http_t *http, /* I - HTTP connection or CUPS_HTTP_DEFAULT */
+ int job_id, /* I - Job ID */
+ int purge) /* I - 1 to purge, 0 to cancel */
+{
+ char uri[HTTP_MAX_URI]; /* Job URI */
+ ipp_t *request; /* IPP request */
/*
- * See if we can connect to the server...
+ * Range check input...
*/
- if (!cups_connect(name, printer, hostname))
+ if (job_id <= 0)
{
- DEBUG_puts("Unable to connect to server!");
-
+ _cupsSetError(IPP_INTERNAL_ERROR, strerror(EINVAL));
return (0);
}
/*
- * Create a printer URI...
+ * Connect to the default server as needed...
*/
- if (httpAssembleURIf(HTTP_URI_CODING_ALL, uri, sizeof(uri), "ipp", NULL,
- "localhost", 0, "/printers/%s", printer) != HTTP_URI_OK)
- {
- _cupsSetError(IPP_INTERNAL_ERROR, NULL);
-
- return (0);
- }
+ if (!http)
+ if ((http = _cupsConnect()) == NULL)
+ return (IPP_SERVICE_UNAVAILABLE);
/*
* Build an IPP_CANCEL_JOB request, which requires the following
*
* attributes-charset
* attributes-natural-language
- * printer-uri
- * job-id
- * [requesting-user-name]
+ * job-uri
+ * requesting-user-name
+ * [purge-job]
*/
request = ippNewRequest(IPP_CANCEL_JOB);
- ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri",
- NULL, uri);
-
- ippAddInteger(request, IPP_TAG_OPERATION, IPP_TAG_INTEGER, "job-id", job);
+ snprintf(uri, sizeof(uri), "ipp://localhost/jobs/%d", job_id);
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "job-uri", NULL, uri);
ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name",
NULL, cupsUser());
+ if (purge)
+ ippAddBoolean(request, IPP_TAG_OPERATION, "purge-job", 1);
/*
* Do the request...
*/
- if ((response = cupsDoRequest(cg->http, request, "/jobs/")) != NULL)
- ippDelete(response);
+ ippDelete(cupsDoRequest(http, request, "/jobs/"));
+
+ return (cupsLastError());
+}
+
+
+/*
+ * 'cupsCreateJob()' - Create an empty job.
+ *
+ * Submit files for printing to the job using the cupsStartDocument(),
+ * cupsWriteRequestData(), and cupsFinishDocument() functions.
+ *
+ * @since CUPS 1.4@
+ */
+
+int /* O - Job ID or 0 on error */
+cupsCreateJob(
+ http_t *http, /* I - HTTP connection or CUPS_HTTP_DEFAULT */
+ const char *name, /* I - Printer or class name */
+ const char *title, /* I - Title of job */
+ 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 */
+
+
+ DEBUG_printf(("cupsCreateJob(http=%p, name=\"%s\", title=\"%s\", "
+ "num_options=%d, options=%p)\n",
+ http, name, title, num_options, options));
+
+ /*
+ * Range check input...
+ */
+
+ if (!name)
+ {
+ _cupsSetError(IPP_INTERNAL_ERROR, NULL);
+ return (0);
+ }
+
+ /*
+ * Build a Create-Job request...
+ */
+
+ if ((request = ippNewRequest(IPP_CREATE_JOB)) == NULL)
+ {
+ _cupsSetError(IPP_INTERNAL_ERROR, NULL);
+ 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...
+ */
+
+ response = cupsDoRequest(http, request, resource);
+
+ if ((attr = ippFindAttribute(response, "job-id", IPP_TAG_INTEGER)) != NULL)
+ job_id = attr->values[0].integer;
- return (cg->last_error < IPP_REDIRECTION_OTHER_SITE);
+ ippDelete(response);
+
+ /*
+ * Return it...
+ */
+
+ return (job_id);
+}
+
+
+/*
+ * 'cupsFinishDocument()' - Finish sending a document.
+ *
+ * @since CUPS 1.4@
+ */
+
+ipp_status_t /* O - Status of document submission */
+cupsFinishDocument(http_t *http, /* I - HTTP connection or CUPS_HTTP_DEFAULT */
+ const char *name) /* I - Printer or class name */
+{
+ char resource[1024]; /* Printer resource */
+
+
+ snprintf(resource, sizeof(resource), "/printers/%s", name);
+
+ ippDelete(cupsGetResponse(http, resource));
+
+ return (cupsLastError());
}
cupsFreeJobs(int num_jobs, /* I - Number of jobs */
cups_job_t *jobs) /* I - Jobs */
{
- int i; /* Looping var */
+ int i; /* Looping var */
+ cups_job_t *job; /* Current job */
- if (num_jobs <= 0 || jobs == NULL)
+ if (num_jobs <= 0 || !jobs)
return;
- for (i = 0; i < num_jobs; i ++)
+ for (i = num_jobs, job = jobs; i > 0; i --, job ++)
{
- free(jobs[i].dest);
- free(jobs[i].user);
- free(jobs[i].format);
- free(jobs[i].title);
+ _cupsStrFree(job->dest);
+ _cupsStrFree(job->user);
+ _cupsStrFree(job->format);
+ _cupsStrFree(job->title);
}
free(jobs);
*response; /* IPP Response */
ipp_attribute_t *attr; /* Current attribute */
char **temp; /* Temporary pointer */
- _cups_globals_t *cg = _cupsGlobals(); /* Pointer to library globals */
+ http_t *http; /* Connection to server */
- if (classes == NULL)
+ if (!classes)
{
_cupsSetError(IPP_INTERNAL_ERROR, NULL);
return (0);
}
- /*
- * Try to connect to the server...
- */
-
- if (!cups_connect("default", NULL, NULL))
- {
- DEBUG_puts("Unable to connect to server!");
+ *classes = NULL;
+ if ((http = _cupsConnect()) == NULL)
return (0);
- }
/*
* Build a CUPS_GET_CLASSES request, which requires the following
* Do the request and get back a response...
*/
- n = 0;
- *classes = NULL;
+ n = 0;
- if ((response = cupsDoRequest(cg->http, request, "/")) != NULL)
+ if ((response = cupsDoRequest(http, request, "/")) != NULL)
{
for (attr = response->attrs; attr != NULL; attr = attr->next)
if (attr->name != NULL &&
const char * /* O - Default printer or NULL */
cupsGetDefault(void)
{
- const char *var; /* Environment variable */
- _cups_globals_t *cg = _cupsGlobals(); /* Pointer to library globals */
-
-
- /*
- * First see if the LPDEST or PRINTER environment variables are
- * set... However, if PRINTER is set to "lp", ignore it to work
- * around a "feature" in most Linux distributions - the default
- * user login scripts set PRINTER to "lp"...
- */
-
- if ((var = getenv("LPDEST")) != NULL)
- return (var);
- else if ((var = getenv("PRINTER")) != NULL && strcmp(var, "lp") != 0)
- return (var);
-
- /*
- * Try to connect to the server...
- */
-
- if (!cups_connect("default", NULL, NULL))
- {
- DEBUG_puts("Unable to connect to server!");
-
- return (NULL);
- }
-
/*
* Return the default printer...
*/
- return (cupsGetDefault2(cg->http));
+ return (cupsGetDefault2(CUPS_HTTP_DEFAULT));
}
return (var);
/*
- * Range check input...
+ * Connect to the server as needed...
*/
if (!http)
- return (NULL);
+ if ((http = _cupsConnect()) == NULL)
+ return (NULL);
/*
* Build a CUPS_GET_DEFAULT request, which requires the following
if ((response = cupsDoRequest(http, request, "/")) != NULL)
{
- if ((attr = ippFindAttribute(response, "printer-name", IPP_TAG_NAME)) != NULL)
+ if ((attr = ippFindAttribute(response, "printer-name",
+ IPP_TAG_NAME)) != NULL)
{
- strlcpy(cg->def_printer, attr->values[0].string.text, sizeof(cg->def_printer));
+ strlcpy(cg->def_printer, attr->values[0].string.text,
+ sizeof(cg->def_printer));
ippDelete(response);
return (cg->def_printer);
}
int completed) /* I - -1 = show all, 0 = active, *
* 1 = completed jobs */
{
- _cups_globals_t *cg = _cupsGlobals(); /* Pointer to library globals */
-
- /*
- * Try to connect to the server...
- */
-
- if (!cups_connect("default", NULL, NULL))
- {
- DEBUG_puts("Unable to connect to server!");
-
- return (-1);
- }
-
/*
* Return the jobs...
*/
- return (cupsGetJobs2(cg->http, jobs, mydest, myjobs, completed));
+ return (cupsGetJobs2(CUPS_HTTP_DEFAULT, jobs, mydest, myjobs, completed));
}
*/
int /* O - Number of jobs */
-cupsGetJobs2(http_t *http, /* I - HTTP connection */
+cupsGetJobs2(http_t *http, /* I - HTTP connection or CUPS_HTTP_DEFAULT */
cups_job_t **jobs, /* O - Job data */
const char *mydest, /* I - NULL = all destinations, *
* otherwise show jobs for mydest */
* Range check input...
*/
- if (!http || !jobs)
+ if (!jobs)
{
_cupsSetError(IPP_INTERNAL_ERROR, NULL);
else
strcpy(uri, "ipp://localhost/jobs");
+ if (!http)
+ if ((http = _cupsConnect()) == NULL)
+ return (-1);
/*
* Build an IPP_GET_JOBS request, which requires the following
if ((response = cupsDoRequest(http, request, "/")) != NULL)
{
- for (attr = response->attrs; attr != NULL; attr = attr->next)
+ for (attr = response->attrs; attr; attr = attr->next)
{
/*
* Skip leading attributes until we hit a job...
*/
- while (attr != NULL && attr->group_tag != IPP_TAG_JOB)
+ while (attr && attr->group_tag != IPP_TAG_JOB)
attr = attr->next;
- if (attr == NULL)
+ if (!attr)
break;
/*
completed_time = 0;
processing_time = 0;
- while (attr != NULL && attr->group_tag == IPP_TAG_JOB)
+ while (attr && attr->group_tag == IPP_TAG_JOB)
{
- if (strcmp(attr->name, "job-id") == 0 &&
+ if (!strcmp(attr->name, "job-id") &&
attr->value_tag == IPP_TAG_INTEGER)
id = attr->values[0].integer;
- else if (strcmp(attr->name, "job-state") == 0 &&
+ else if (!strcmp(attr->name, "job-state") &&
attr->value_tag == IPP_TAG_ENUM)
state = (ipp_jstate_t)attr->values[0].integer;
- else if (strcmp(attr->name, "job-priority") == 0 &&
+ else if (!strcmp(attr->name, "job-priority") &&
attr->value_tag == IPP_TAG_INTEGER)
priority = attr->values[0].integer;
- else if (strcmp(attr->name, "job-k-octets") == 0 &&
+ else if (!strcmp(attr->name, "job-k-octets") &&
attr->value_tag == IPP_TAG_INTEGER)
size = attr->values[0].integer;
- else if (strcmp(attr->name, "time-at-completed") == 0 &&
+ else if (!strcmp(attr->name, "time-at-completed") &&
attr->value_tag == IPP_TAG_INTEGER)
completed_time = attr->values[0].integer;
- else if (strcmp(attr->name, "time-at-creation") == 0 &&
+ else if (!strcmp(attr->name, "time-at-creation") &&
attr->value_tag == IPP_TAG_INTEGER)
creation_time = attr->values[0].integer;
- else if (strcmp(attr->name, "time-at-processing") == 0 &&
+ else if (!strcmp(attr->name, "time-at-processing") &&
attr->value_tag == IPP_TAG_INTEGER)
processing_time = attr->values[0].integer;
- else if (strcmp(attr->name, "job-printer-uri") == 0 &&
+ else if (!strcmp(attr->name, "job-printer-uri") &&
attr->value_tag == IPP_TAG_URI)
{
if ((dest = strrchr(attr->values[0].string.text, '/')) != NULL)
dest ++;
}
- else if (strcmp(attr->name, "job-originating-user-name") == 0 &&
+ else if (!strcmp(attr->name, "job-originating-user-name") &&
attr->value_tag == IPP_TAG_NAME)
user = attr->values[0].string.text;
- else if (strcmp(attr->name, "document-format") == 0 &&
+ else if (!strcmp(attr->name, "document-format") &&
attr->value_tag == IPP_TAG_MIMETYPE)
format = attr->values[0].string.text;
- else if (strcmp(attr->name, "job-name") == 0 &&
+ else if (!strcmp(attr->name, "job-name") &&
(attr->value_tag == IPP_TAG_TEXT ||
attr->value_tag == IPP_TAG_NAME))
title = attr->values[0].string.text;
* See if we have everything needed...
*/
- if (dest == NULL || id == 0)
+ if (!dest || !id)
{
- if (attr == NULL)
+ if (!attr)
break;
else
continue;
else
temp = realloc(*jobs, sizeof(cups_job_t) * (n + 1));
- if (temp == NULL)
+ if (!temp)
{
/*
* Ran out of memory!
*/
+ _cupsSetError(IPP_INTERNAL_ERROR, strerror(errno));
+
cupsFreeJobs(n, *jobs);
*jobs = NULL;
ippDelete(response);
- return (0);
+
+ return (-1);
}
*jobs = temp;
* Copy the data over...
*/
- temp->dest = strdup(dest);
- temp->user = strdup(user);
- temp->format = strdup(format);
- temp->title = strdup(title);
+ temp->dest = _cupsStrAlloc(dest);
+ temp->user = _cupsStrAlloc(user);
+ temp->format = _cupsStrAlloc(format);
+ temp->title = _cupsStrAlloc(title);
temp->id = id;
temp->priority = priority;
temp->state = state;
temp->creation_time = creation_time;
temp->processing_time = processing_time;
- if (attr == NULL)
+ if (!attr)
break;
}
time_t modtime = 0; /* Modification time */
- /*
- * See if we can connect to the server...
- */
-
- if (!cups_connect(name, NULL, NULL))
- {
- DEBUG_puts("Unable to connect to server!");
-
- return (NULL);
- }
-
/*
* Return the PPD file...
*/
cg->ppd_filename[0] = '\0';
- if (cupsGetPPD3(cg->http, name, &modtime, cg->ppd_filename,
+ if (cupsGetPPD3(CUPS_HTTP_DEFAULT, name, &modtime, cg->ppd_filename,
sizeof(cg->ppd_filename)) == HTTP_OK)
return (cg->ppd_filename);
else
*/
const char * /* O - Filename for PPD file */
-cupsGetPPD2(http_t *http, /* I - HTTP connection */
+cupsGetPPD2(http_t *http, /* I - HTTP connection or CUPS_HTTP_DEFAULT */
const char *name) /* I - Printer name */
{
_cups_globals_t *cg = _cupsGlobals(); /* Pointer to library globals */
*/
http_status_t /* O - HTTP status */
-cupsGetPPD3(http_t *http, /* I - HTTP connection */
+cupsGetPPD3(http_t *http, /* I - HTTP connection or CUPS_HTTP_DEFAULT */
const char *name, /* I - Printer name */
time_t *modtime, /* IO - Modification time */
char *buffer, /* I - Filename buffer */
"bufsize=%d)\n", http, name ? name : "(null)", modtime,
modtime ? *modtime : 0, buffer, (int)bufsize));
- if (!http)
- {
- _cupsSetError(IPP_INTERNAL_ERROR, "No HTTP connection!");
- return (HTTP_NOT_ACCEPTABLE);
- }
-
if (!name)
{
_cupsSetError(IPP_INTERNAL_ERROR, "No printer name!");
* Try finding a printer URI for this printer...
*/
+ if (!http)
+ http = _cupsConnect();
+
if (!cups_get_printer_uri(http, name, hostname, sizeof(hostname), &port,
resource, sizeof(resource), 0))
return (HTTP_NOT_FOUND);
*response; /* IPP Response */
ipp_attribute_t *attr; /* Current attribute */
char **temp; /* Temporary pointer */
- _cups_globals_t *cg = _cupsGlobals(); /* Pointer to library globals */
+ http_t *http; /* Connection to server */
+
+ /*
+ * Range check input...
+ */
- if (printers == NULL)
+ if (!printers)
{
_cupsSetError(IPP_INTERNAL_ERROR, NULL);
return (0);
}
+ *printers = NULL;
+
/*
* Try to connect to the server...
*/
- if (!cups_connect("default", NULL, NULL))
- {
- DEBUG_puts("Unable to connect to server!");
-
+ if ((http = _cupsConnect()) == NULL)
return (0);
- }
/*
* Build a CUPS_GET_PRINTERS request, which requires the following
* Do the request and get back a response...
*/
- n = 0;
- *printers = NULL;
+ n = 0;
- if ((response = cupsDoRequest(cg->http, request, "/")) != NULL)
+ if ((response = cupsDoRequest(http, request, "/")) != NULL)
{
for (attr = response->attrs; attr != NULL; attr = attr->next)
if (attr->name != NULL &&
*/
char * /* O - Name of PPD file or NULL on error */
-cupsGetServerPPD(http_t *http, /* I - HTTP connection */
+cupsGetServerPPD(http_t *http, /* I - HTTP connection or CUPS_HTTP_DEFAULT */
const char *name) /* I - Name of PPD file ("ppd-name") */
{
int fd; /* PPD file descriptor */
* Range check input...
*/
- if (!http || !name)
+ if (!name)
{
- if (!http)
- _cupsSetError(IPP_INTERNAL_ERROR, "No HTTP connection!");
- else
- _cupsSetError(IPP_INTERNAL_ERROR, "No PPD name!");
+ _cupsSetError(IPP_INTERNAL_ERROR, "No PPD name!");
return (NULL);
}
+ if (!http)
+ if ((http = _cupsConnect()) == NULL)
+ return (NULL);
+
/*
* Get a temp file...
*/
"title=\"%s\", num_options=%d, options=%p)\n",
name, filename, title, num_options, options));
- return (cupsPrintFiles(name, 1, &filename, title, num_options, options));
+ return (cupsPrintFiles2(CUPS_HTTP_DEFAULT, name, 1, &filename, title,
+ num_options, options));
}
*/
int /* O - Job ID */
-cupsPrintFile2(http_t *http, /* I - HTTP connection */
- const char *name, /* I - Printer or class name */
- const char *filename, /* I - File to print */
- const char *title, /* I - Title of job */
- int num_options,
- /* I - Number of options */
- cups_option_t *options) /* I - Options */
+cupsPrintFile2(
+ http_t *http, /* I - HTTP connection */
+ const char *name, /* I - Printer or class name */
+ const char *filename, /* I - File to print */
+ const char *title, /* I - Title of job */
+ 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));
- return (cupsPrintFiles2(http, name, 1, &filename, title, num_options, options));
+ return (cupsPrintFiles2(http, name, 1, &filename, title, num_options,
+ options));
}
*/
int /* O - Job ID */
-cupsPrintFiles(const char *name, /* I - Printer or class name */
- int num_files, /* I - Number of files */
- const char **files, /* I - File(s) to print */
- const char *title, /* I - Title of job */
- int num_options,
- /* I - Number of options */
- cups_option_t *options) /* I - Options */
+cupsPrintFiles(
+ const char *name, /* I - Printer or class name */
+ int num_files, /* I - Number of files */
+ const char **files, /* I - File(s) to print */
+ const char *title, /* I - Title of job */
+ int num_options, /* I - Number of options */
+ cups_option_t *options) /* I - Options */
{
- _cups_globals_t *cg = _cupsGlobals(); /* Pointer to library globals */
-
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));
- /*
- * Setup a connection and request data...
- */
-
- if (!cups_connect(name, NULL, NULL))
- {
- DEBUG_printf(("cupsPrintFiles: Unable to open connection - %s.\n",
- strerror(errno)));
- DEBUG_puts("Unable to connect to server!");
-
- return (0);
- }
-
/*
* Print the file(s)...
*/
- return (cupsPrintFiles2(cg->http, name, num_files, files, title,
+ return (cupsPrintFiles2(CUPS_HTTP_DEFAULT, name, num_files, files, title,
num_options, options));
}
-
/*
* 'cupsPrintFiles2()' - Print one or more files to a printer or class on the
* specified server.
*/
int /* O - Job ID */
-cupsPrintFiles2(http_t *http, /* I - HTTP connection */
- const char *name, /* I - Printer or class name */
- int num_files,/* I - Number of files */
- const char **files, /* I - File(s) to print */
- const char *title, /* I - Title of job */
- int num_options,
- /* I - Number of options */
- cups_option_t *options) /* I - Options */
+cupsPrintFiles2(
+ http_t *http, /* I - HTTP connection or CUPS_HTTP_DEFAULT */
+ const char *name, /* I - Printer or class name */
+ int num_files, /* I - Number of files */
+ const char **files, /* I - File(s) to print */
+ const char *title, /* I - Title of job */
+ int num_options, /* I - Number of options */
+ cups_option_t *options) /* I - Options */
{
int i; /* Looping var */
- const char *val; /* Pointer to option value */
- ipp_t *request; /* IPP request */
- ipp_t *response; /* IPP response */
- ipp_attribute_t *attr; /* IPP job-id attribute */
- char uri[HTTP_MAX_URI]; /* Printer URI */
- int jobid; /* New job ID */
- const char *base; /* Basename of current filename */
+ int job_id; /* New job ID */
+ const char *docname; /* Basename of current filename */
+ const char *format; /* Document format */
+ cups_file_t *fp; /* Current file */
+ char buffer[8192]; /* Copy buffer */
+ ssize_t bytes; /* Bytes in buffer */
+ http_status_t status; /* Status of write */
- DEBUG_printf(("cupsPrintFiles(http=%p, name=\"%s\", num_files=%d, "
+ 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));
* Range check input...
*/
- if (!http || !name || num_files < 1 || files == NULL)
+ if (!name || num_files < 1 || !files)
{
_cupsSetError(IPP_INTERNAL_ERROR, NULL);
}
/*
- * Setup the printer URI...
+ * Create the print job...
*/
- if (httpAssembleURIf(HTTP_URI_CODING_ALL, uri, sizeof(uri), "ipp", NULL,
- "localhost", 0, "/printers/%s", name) != HTTP_URI_OK)
- {
- _cupsSetError(IPP_INTERNAL_ERROR, NULL);
-
+ if ((job_id = cupsCreateJob(http, name, title, num_options, options)) == 0)
return (0);
- }
/*
- * Build a standard CUPS URI for the printer and fill the standard IPP
- * attributes...
+ * Send each of the files...
*/
- if ((request = ippNewRequest(num_files == 1 ? IPP_PRINT_JOB :
- IPP_CREATE_JOB)) == NULL)
- {
- _cupsSetError(IPP_INTERNAL_ERROR, NULL);
-
- return (0);
- }
-
- ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri",
- NULL, uri);
-
- ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name",
- NULL, cupsUser());
+ if (cupsGetOption("raw", num_options, options))
+ format = CUPS_FORMAT_RAW;
+ else if ((format = cupsGetOption("document-format", num_options,
+ options)) == NULL)
+ format = CUPS_FORMAT_AUTO;
- if (title)
- ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "job-name", NULL,
- title);
-
- /*
- * Then add all options...
- */
-
- cupsEncodeOptions(request, num_options, options);
-
- /*
- * Do the request...
- */
-
- snprintf(uri, sizeof(uri), "/printers/%s", name);
+ for (i = 0; i < num_files; i ++)
+ {
+ /*
+ * Start the next file...
+ */
- if (num_files == 1)
- response = cupsDoFileRequest(http, request, uri, *files);
- else
- response = cupsDoRequest(http, request, uri);
+ if ((docname = strrchr(files[i], '/')) != NULL)
+ docname ++;
+ else
+ docname = files[i];
- if (response == NULL)
- jobid = 0;
- else if (response->request.status.status_code > IPP_OK_CONFLICT)
- {
- DEBUG_printf(("IPP response code was 0x%x!\n",
- response->request.status.status_code));
- jobid = 0;
- }
- else if ((attr = ippFindAttribute(response, "job-id", IPP_TAG_INTEGER)) == NULL)
- {
- DEBUG_puts("No job ID!");
+ if ((fp = cupsFileOpen(files[i], "rb")) == NULL)
+ {
+ /*
+ * Unable to open print file, cancel the job and return...
+ */
- _cupsSetError(IPP_INTERNAL_ERROR, NULL);
+ cupsCancelJob2(http, job_id, 0);
+ return (0);
+ }
- jobid = 0;
- }
- else
- jobid = attr->values[0].integer;
+ status = cupsStartDocument(http, name, job_id, docname, format,
+ i == (num_files - 1));
- if (response != NULL)
- ippDelete(response);
+ while (status == HTTP_CONTINUE &&
+ (bytes = cupsFileRead(fp, buffer, sizeof(buffer))) > 0)
+ status = cupsWriteRequestData(http, buffer, bytes);
- /*
- * Handle multiple file jobs if the create-job operation worked...
- */
+ cupsFileClose(fp);
- if (jobid > 0 && num_files > 1)
- for (i = 0; i < num_files; i ++)
+ if (status != HTTP_CONTINUE || cupsFinishDocument(http, name) != IPP_OK)
{
/*
- * Build a standard CUPS URI for the job and fill the standard IPP
- * attributes...
+ * Unable to queue, cancel the job and return...
*/
- if ((request = ippNewRequest(IPP_SEND_DOCUMENT)) == NULL)
- return (0);
-
- snprintf(uri, sizeof(uri), "ipp://localhost/jobs/%d", jobid);
+ cupsCancelJob2(http, job_id, 0);
+ return (0);
+ }
+ }
- ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "job-uri",
- NULL, uri);
+ return (job_id);
+}
- /*
- * Handle raw print files...
- */
- if (cupsGetOption("raw", num_options, options))
- ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_MIMETYPE,
- "document-format", NULL, "application/vnd.cups-raw");
- else if ((val = cupsGetOption("document-format", num_options,
- options)) != NULL)
- ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_MIMETYPE,
- "document-format", NULL, val);
- else
- ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_MIMETYPE,
- "document-format", NULL, "application/octet-stream");
+/*
+ * 'cupsStartDocument()' - Add a document to a job created with cupsCreateJob().
+ *
+ * Use cupsWriteRequestData() to write data for the document and
+ * cupsFinishDocument() to finish the document and get the submission status.
+ *
+ * The MIME type constants CUPS_FORMAT_AUTO, CUPS_FORMAT_PDF,
+ * CUPS_FORMAT_POSTSCRIPT, CUPS_FORMAT_RAW, and CUPS_FORMAT_TEXT are provided
+ * for the "format" argument, although any supported MIME type string can be
+ * supplied.
+ *
+ * @since CUPS 1.4@
+ */
- ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME,
- "requesting-user-name", NULL, cupsUser());
+http_status_t /* O - HTTP status of request */
+cupsStartDocument(
+ http_t *http, /* I - HTTP connection or CUPS_HTTP_DEFAULT */
+ const char *name, /* I - Printer or class name */
+ int job_id, /* I - Job ID from cupsCreateJob() */
+ const char *docname, /* I - Name of document */
+ const char *format, /* I - MIME type or CUPS_FORMAT_foo */
+ int last_document) /* I - 1 for last document in job, 0 otherwise */
+{
+ char resource[1024], /* Resource for destinatio */
+ printer_uri[1024]; /* Printer URI */
+ ipp_t *request; /* Send-Document request */
+ http_status_t status; /* HTTP status */
- /*
- * Add the original document filename...
- */
- if ((base = strrchr(files[i], '/')) != NULL)
- base ++;
- else
- base = files[i];
+ /*
+ * Create a Send-Document request...
+ */
- ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "document-name",
- NULL, base);
+ if ((request = ippNewRequest(IPP_SEND_DOCUMENT)) == NULL)
+ {
+ _cupsSetError(IPP_INTERNAL_ERROR, NULL);
+ return (0);
+ }
- /*
- * Is this the last document?
- */
+ httpAssembleURIf(HTTP_URI_CODING_ALL, printer_uri, sizeof(printer_uri), "ipp",
+ NULL, "localhost", ippPort(), "/printers/%s", name);
+ snprintf(resource, sizeof(resource), "/printers/%s", name);
- if (i == (num_files - 1))
- ippAddBoolean(request, IPP_TAG_OPERATION, "last-document", 1);
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri",
+ NULL, printer_uri);
+ ippAddInteger(request, IPP_TAG_OPERATION, IPP_TAG_INTEGER, "job-id", job_id);
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name",
+ NULL, cupsUser());
+ if (docname)
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "document-name",
+ NULL, docname);
+ if (format)
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_MIMETYPE,
+ "document-format", NULL, format);
+ ippAddBoolean(request, IPP_TAG_OPERATION, "last-document", last_document);
- /*
- * Send the file...
- */
+ /*
+ * Send and delete the request, then return the status...
+ */
- snprintf(uri, sizeof(uri), "/printers/%s", name);
+ status = cupsSendRequest(http, request, resource, CUPS_LENGTH_VARIABLE);
- if ((response = cupsDoFileRequest(http, request, uri,
- files[i])) != NULL)
- ippDelete(response);
- }
+ ippDelete(request);
- return (jobid);
+ return (status);
}
/*
- * 'cups_connect()' - Connect to the specified host...
+ * '_cupsConnect()' - Get the default server connection...
*/
-static char * /* I - Printer name or NULL */
-cups_connect(const char *name, /* I - Destination (printer[@host]) */
- char *printer, /* O - Printer name [HTTP_MAX_URI] */
- char *hostname) /* O - Hostname [HTTP_MAX_URI] */
+http_t * /* O - HTTP connection */
+_cupsConnect(void)
{
- char hostbuf[HTTP_MAX_URI], /* Name of host */
- http_hostname[HTTP_MAX_HOST]; /* Hostname associated with connection */
- _cups_globals_t *cg = _cupsGlobals();/* Pointer to library globals */
-
-
- DEBUG_printf(("cups_connect(\"%s\", %p, %p)\n", name, printer, hostname));
-
- if (name == NULL)
- {
- _cupsSetError(IPP_BAD_REQUEST, NULL);
+ _cups_globals_t *cg = _cupsGlobals(); /* Pointer to library globals */
- return (NULL);
- }
/*
- * All jobs are now queued to cupsServer() to avoid hostname
- * resolution problems and to ensure that the user sees all
- * locally queued jobs locally.
+ * See if we are connected to the same server...
*/
- strlcpy(hostbuf, cupsServer(), sizeof(hostbuf));
+ if (cg->http)
+ {
+ int port; /* Port for connection */
- httpGetHostname(cg->http, http_hostname, sizeof(http_hostname));
- if (hostname != NULL)
- strlcpy(hostname, hostbuf, HTTP_MAX_URI);
- else
- hostname = hostbuf;
+ /*
+ * Get the port associated with the current connection...
+ */
- if (printer != NULL)
- strlcpy(printer, name, HTTP_MAX_URI);
- else
- printer = (char *)name;
+#ifdef AF_INET6
+ if (cg->http->hostaddr->addr.sa_family == AF_INET6)
+ port = ntohs(cg->http->hostaddr->ipv6.sin6_port);
+ else
+#endif /* AF_INET6 */
+ if (cg->http->hostaddr->addr.sa_family == AF_INET)
+ port = ntohs(cg->http->hostaddr->ipv4.sin_port);
+ else
+ port = cg->ipp_port;
- if (cg->http != NULL)
- {
- if (!strcasecmp(http_hostname, hostname))
- return (printer);
+ /*
+ * 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 != port ||
+ (cg->http->encryption != cg->encryption &&
+ cg->http->encryption == HTTP_ENCRYPT_NEVER))
+ {
+ /*
+ * Need to close the current connection because something has changed...
+ */
- httpClose(cg->http);
+ httpClose(cg->http);
+ cg->http = NULL;
+ }
}
- DEBUG_printf(("connecting to %s on port %d...\n", hostname, ippPort()));
+ /*
+ * (Re)connect as needed...
+ */
- if ((cg->http = httpConnectEncrypt(hostname, ippPort(),
- cupsEncryption())) == NULL)
+ if (!cg->http)
{
- DEBUG_puts("Unable to connect to server!");
+ if ((cg->http = httpConnectEncrypt(cupsServer(), ippPort(),
+ cupsEncryption())) == NULL)
+ _cupsSetError(IPP_SERVICE_UNAVAILABLE,
+ errno ? strerror(errno) : "Unable to connect to host.");
+ }
- _cupsSetError(IPP_SERVICE_UNAVAILABLE, strerror(errno));
+ /*
+ * Return the cached connection...
+ */
- return (NULL);
- }
- else
- return (printer);
+ return (cg->http);
}
%
% PostScript test page for the Common UNIX Printing System ("CUPS").
%
-% Copyright 2007 Apple Inc.
+% Copyright 2007-2008 Apple Inc.
% Copyright 1993-2007 Easy Software Products
%
% These coded instructions, statements, and computer programs are the
pageWidth 17 mul % Center of page
pageHeight 10 mul % Bottom of page
moveto % Position text
- (Printed Using CUPS v1.3.x) show
+ (Printed Using CUPS v1.4.x) show
pageWidth 17 mul % Left side of page
pageHeight 8 mul % Move down...
2 copy moveto % Position text
smallFont setfont % Font
- (Copyright 2007 Apple Inc., All Rights Reserved. CUPS and the CUPS logo are the trademark) show
+ (Copyright 2007-2008 Apple Inc., All Rights Reserved. CUPS and the CUPS logo are the) show
pageHeight 2 add sub % Move down...
2 copy moveto % Position text
- (property of Apple Inc., 1 Infinite Loop, Cupertino, CA 95014, USA.) show
+ (trademark property of Apple Inc., 1 Infinite Loop, Cupertino, CA 95014, USA.) show
pageHeight 2 mul 4 add sub % Move down...
moveto % Position text
(Need help? Contact your operating system vendor or visit "http://www.cups.org/".) show
<TR><TD> </TD></TR>
<TR><TD CLASS="trailer">The Common UNIX Printing System, CUPS, and
the CUPS logo are the trademark property of
-<A HREF="http://www.apple.com">Apple Inc.</A> CUPS is copyright 2007 by Apple
-Inc., all rights reserved.</TD></TR>
+<A HREF="http://www.apple.com">Apple Inc.</A> CUPS is copyright 2007-2008 by
+Apple Inc., all rights reserved.</TD></TR>
</TABLE>
</BODY>
</HTML>
.\"
.\" cupsd.conf man page for the Common UNIX Printing System (CUPS).
.\"
-.\" Copyright 2007 by Apple Inc.
+.\" Copyright 2007-2008 by Apple Inc.
.\" Copyright 1997-2006 by Easy Software Products.
.\"
.\" These coded instructions, statements, and computer programs are the
.\" 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/".
.\"
-.TH cupsd.conf 5 "Common UNIX Printing System" "6 June 2006" "Apple Inc."
+.TH cupsd.conf 5 "Common UNIX Printing System" "2 January 2008" "Apple Inc."
.SH NAME
cupsd.conf \- server configuration file for cups
.SH DESCRIPTION
.br
Specifies the default access policy to use.
.TP 5
+DefaultShared Yes
+.TP 5
+DefaultShared No
+.br
+Specifies whether local printers are shared by default.
+.TP 5
Deny all
.TP 5
Deny none
.br
http://localhost:631/help
.SH COPYRIGHT
-Copyright 2007 by Apple Inc.
+Copyright 2007-2008 by Apple Inc.
.\"
.\" End of "$Id: cupsd.conf.man.in 7002 2007-10-01 23:07:37Z mike $".
.\"
.\"
.\" lpadmin man page for the Common UNIX Printing System (CUPS).
.\"
-.\" Copyright 2007 by Apple Inc.
+.\" Copyright 2007-2008 by Apple Inc.
.\" Copyright 1997-2006 by Easy Software Products.
.\"
.\" These coded instructions, statements, and computer programs are the
.\" 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/".
.\"
-.TH lpadmin 8 "Common UNIX Printing System" "13 July 2006" "Apple Inc."
+.TH lpadmin 8 "Common UNIX Printing System" "2 January 2008" "Apple Inc."
.SH NAME
lpadmin \- configure cups printers and classes
.SH SYNOPSIS
Sets a standard System V interface script or PPD file from the
\fImodel\fR directory.
.TP 5
--o name=value
-.br
-Sets a PPD or server option for the printer. PPD options can be
-listed using the \fI-l\fR option with the \fIlpoptions(1)\fR
-command.
-.TP 5
-o job-k-limit=value
.br
Sets the kilobyte limit for per-user quotas. The value is an
.br
Sets the default banner page(s) to use for print jobs.
.TP 5
+-o name=value
+.br
+Sets a PPD option for the printer. PPD options can be
+listed using the \fI-l\fR option with the \fIlpoptions(1)\fR
+command.
+.TP 5
+-o name-default=value
+.br
+Sets a default server-side option for the printer. Any print-time
+option can be defaulted, e.g. "-o cpi-default=17" to set the default
+"cpi" option value to 17.
+.TP 5
-o port-monitor=name
.br
Sets the binary communications program to use when printing,
-"none", "bcp", or "tbcp". The default program is "none".
+"none", "bcp", or "tbcp". The default program is "none". The
+specified port monitor must be listed in the printer's PPD file.
.TP 5
-o printer-error-policy=name
.br
.br
http://localhost:631/help
.SH COPYRIGHT
-Copyright 2007 by Apple Inc.
+Copyright 2007-2008 by Apple Inc.
.\"
.\" End of "$Id: lpadmin.man 6649 2007-07-11 21:46:42Z mike $".
.\"
.\"
.\" lpq man page for the Common UNIX Printing System (CUPS).
.\"
-.\" Copyright 2007 by Apple Inc.
+.\" Copyright 2007-2008 by Apple Inc.
.\" Copyright 1997-2006 by Easy Software Products.
.\"
.\" These coded instructions, statements, and computer programs are the
.\" 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/".
.\"
-.TH lpq 1 "Common UNIX Printing System" "12 February 2006" "Apple Inc."
+.TH lpq 1 "Common UNIX Printing System" "2 January 2008" "Apple Inc."
.SH NAME
lpq \- show printer queue status
.SH SYNOPSIS
.LP
The \fI+interval\fR option allows you to continuously report the
jobs in the queue until the queue is empty; the list of jobs is
-show one every \fIinterval\fR seconds.
+show once every \fIinterval\fR seconds.
.SH OPTIONS
\fIlpq\fR supports the following options:
.TP 5
.br
http://localhost:631/help
.SH COPYRIGHT
-Copyright 2007 by Apple Inc.
+Copyright 2007-2008 by Apple Inc.
.\"
.\" End of "$Id: lpq.man 6649 2007-07-11 21:46:42Z mike $".
.\"
// write PostScript file
psOut = new PSOutputDev(psFileName->getCString(), doc->getXRef(),
doc->getCatalog(), 1, doc->getNumPages(),
- psModePS, 0, 0, 0, 0, gFalse,
- cupsGetOption("page-ranges", num_options, options));
+ psModePS, 0, 0, 0, 0, gFalse, NULL);
if (psOut->isOk())
doc->displayPages(psOut, 1, doc->getNumPages(), 72.0, 72.0, 0,
gTrue, gFalse, gFalse);
/*
- * "$Id: lp.c 6649 2007-07-11 21:46:42Z mike $"
+ * "$Id: lp.c 7170 2008-01-04 02:21:30Z mike $"
*
* "lp" command for the Common UNIX Printing System (CUPS).
*
* main() - Parse options and send files for printing.
* restart_job() - Restart a job.
* set_job_attrs() - Set job attributes.
- * sighandler() - Signal catcher for when we print from stdin...
*/
/*
#include <cups/i18n.h>
-#ifndef WIN32
-# include <unistd.h>
-# include <signal.h>
-
-
/*
* Local functions.
*/
-void sighandler(int);
-#endif /* !WIN32 */
int restart_job(const char *command, int job_id);
int set_job_attrs(const char *command, int job_id, int num_options,
cups_option_t *options);
-/*
- * Globals...
- */
-
-char tempfile[1024]; /* Temporary file for printing from stdin */
-
-
/*
* 'main()' - Parse options and send files for printing.
*/
int end_options; /* No more options? */
int silent; /* Silent or verbose output? */
char buffer[8192]; /* Copy buffer */
- ssize_t bytes; /* Bytes copied */
- off_t filesize; /* Size of temp file */
- int temp; /* Temporary file descriptor */
-#if defined(HAVE_SIGACTION) && !defined(HAVE_SIGSET)
- struct sigaction action; /* Signal action */
- struct sigaction oldaction; /* Old signal action */
-#endif /* HAVE_SIGACTION && !HAVE_SIGSET*/
#ifdef __sun
if (num_files > 0)
job_id = cupsPrintFiles(printer, num_files, files, title, num_options, options);
- else
+ else if ((job_id = cupsCreateJob(CUPS_HTTP_DEFAULT, printer,
+ title ? title : "(stdin)",
+ num_options, options)) > 0)
{
- num_files = 1;
-
-#ifndef WIN32
-# if defined(HAVE_SIGSET)
- sigset(SIGHUP, sighandler);
- if (sigset(SIGINT, sighandler) == SIG_IGN)
- sigset(SIGINT, SIG_IGN);
- sigset(SIGTERM, sighandler);
-# elif defined(HAVE_SIGACTION)
- memset(&action, 0, sizeof(action));
- action.sa_handler = sighandler;
-
- sigaction(SIGHUP, &action, NULL);
- sigaction(SIGINT, NULL, &oldaction);
- if (oldaction.sa_handler != SIG_IGN)
- sigaction(SIGINT, &action, NULL);
- sigaction(SIGTERM, &action, NULL);
-# else
- signal(SIGHUP, sighandler);
- if (signal(SIGINT, sighandler) == SIG_IGN)
- signal(SIGINT, SIG_IGN);
- signal(SIGTERM, sighandler);
-# endif
-#endif /* !WIN32 */
-
- temp = cupsTempFd(tempfile, sizeof(tempfile));
-
- if (temp < 0)
- {
- _cupsLangPrintf(stderr,
- _("%s: Error - unable to create temporary file \"%s\" - %s\n"),
- argv[0], tempfile, strerror(errno));
- return (1);
- }
+ http_status_t status; /* Write status */
+ const char *format; /* Document format */
+ ssize_t bytes; /* Bytes read */
- while ((bytes = read(0, buffer, sizeof(buffer))) > 0)
- if (write(temp, buffer, bytes) < 0)
- {
- _cupsLangPrintf(stderr,
- _("%s: Error - unable to write to temporary file "
- "\"%s\" - %s\n"),
- argv[0], tempfile, strerror(errno));
- close(temp);
- unlink(tempfile);
- return (1);
- }
- filesize = lseek(temp, 0, SEEK_CUR);
- close(temp);
+ if (cupsGetOption("raw", num_options, options))
+ format = CUPS_FORMAT_RAW;
+ else if ((format = cupsGetOption("document-format", num_options,
+ options)) == NULL)
+ format = CUPS_FORMAT_AUTO;
+
+ status = cupsStartDocument(CUPS_HTTP_DEFAULT, printer, job_id, NULL,
+ format, 1);
- if (filesize <= 0)
+ while (status == HTTP_CONTINUE &&
+ (bytes = read(0, buffer, sizeof(buffer))) > 0)
+ status = cupsWriteRequestData(CUPS_HTTP_DEFAULT, buffer, bytes);
+
+ if (status != HTTP_CONTINUE)
{
_cupsLangPrintf(stderr,
- _("%s: Error - stdin is empty, so no job has been sent.\n"),
- argv[0]);
- unlink(tempfile);
+ _("%s: Error - unable to queue from stdin - %s\n"),
+ argv[0], httpStatus(status));
return (1);
}
- if (title)
- job_id = cupsPrintFile(printer, tempfile, title, num_options, options);
- else
- job_id = cupsPrintFile(printer, tempfile, "(stdin)", num_options, options);
-
- unlink(tempfile);
+ if (cupsFinishDocument(CUPS_HTTP_DEFAULT, printer) != IPP_OK)
+ job_id = 0;
}
if (job_id < 1)
restart_job(const char *command, /* I - Command name */
int job_id) /* I - Job ID */
{
- http_t *http; /* HTTP connection to server */
ipp_t *request; /* IPP request */
char uri[HTTP_MAX_URI]; /* URI for job */
- http = httpConnectEncrypt(cupsServer(), ippPort(), cupsEncryption());
-
request = ippNewRequest(IPP_RESTART_JOB);
sprintf(uri, "ipp://localhost/jobs/%d", job_id);
ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME,
"requesting-user-name", NULL, cupsUser());
- ippDelete(cupsDoRequest(http, request, "/jobs"));
+ ippDelete(cupsDoRequest(CUPS_HTTP_DEFAULT, request, "/jobs"));
if (cupsLastError() > IPP_OK_CONFLICT)
{
int num_options,/* I - Number of options */
cups_option_t *options) /* I - Options */
{
- http_t *http; /* HTTP connection to server */
ipp_t *request; /* IPP request */
char uri[HTTP_MAX_URI]; /* URI for job */
if (num_options == 0)
return (0);
- http = httpConnectEncrypt(cupsServer(), ippPort(), cupsEncryption());
-
request = ippNewRequest(IPP_SET_JOB_ATTRIBUTES);
sprintf(uri, "ipp://localhost/jobs/%d", job_id);
cupsEncodeOptions(request, num_options, options);
- ippDelete(cupsDoRequest(http, request, "/jobs"));
+ ippDelete(cupsDoRequest(CUPS_HTTP_DEFAULT, request, "/jobs"));
if (cupsLastError() > IPP_OK_CONFLICT)
{
}
-#ifndef WIN32
-/*
- * 'sighandler()' - Signal catcher for when we print from stdin...
- */
-
-void
-sighandler(int s) /* I - Signal number */
-{
- /*
- * Remove the temporary file we're using to print from stdin...
- */
-
- unlink(tempfile);
-
- /*
- * Exit...
- */
-
- exit(s);
-}
-#endif /* !WIN32 */
-
-
/*
- * End of "$Id: lp.c 6649 2007-07-11 21:46:42Z mike $".
+ * End of "$Id: lp.c 7170 2008-01-04 02:21:30Z mike $".
*/
<TR><TD> </TD></TR>
<TR><TD CLASS="trailer">The Common UNIX Printing System, CUPS, and
the CUPS logo are the trademark property of
-<A HREF="http://www.apple.com">Apple Inc.</A> CUPS is copyright 2007 by Apple
-Inc., all rights reserved.</TD></TR>
+<A HREF="http://www.apple.com">Apple Inc.</A> CUPS is copyright 2007-2008 by
+Apple Inc., all rights reserved.</TD></TR>
</TABLE>
</BODY>
</HTML>