-CHANGES.txt - 2007-03-19
+CHANGES.txt - 2007-03-21
------------------------
CHANGES IN CUPS V1.3
- Documentation updates (STR #2130, STR #2131)
+ - The scheduler now reports the PostScript product string
+ from PPD files in CUPS-Get-PPDs responses (STR #1900)
+ - Raw printing with queues pointing to the file pseudo-
+ device and multiple files and/or banners now works (STR
+ #1933)
- Added new public cupsAdminGetServerSettings() and
cupsAdminSetServerSettings() APIs.
- Added new "makebuttons" script in the "tools" directory
/*
- * "$Id: admin.c 6361 2007-03-19 16:01:28Z mike $"
+ * "$Id: admin.c 6378 2007-03-21 07:18:18Z mike $"
*
* Administration CGI for the Common UNIX Printing System (CUPS).
*
* Get the current server settings...
*/
- if (!_cupsAdminGetServerSettings(http, &num_settings, &settings))
+ if (!cupsAdminGetServerSettings(http, &num_settings, &settings))
{
cgiStartHTML(cgiText(_("Change Settings")));
cgiSetVariable("MESSAGE",
num_settings, &settings);
#endif /* HAVE_GSSAPI */
- if (!_cupsAdminSetServerSettings(http, num_settings, settings))
+ if (!cupsAdminSetServerSettings(http, num_settings, settings))
{
cgiStartHTML(cgiText(_("Change Settings")));
cgiSetVariable("MESSAGE",
* Get the current server settings...
*/
- if (!_cupsAdminGetServerSettings(http, &num_settings, &settings))
+ if (!cupsAdminGetServerSettings(http, &num_settings, &settings))
{
cgiSetVariable("SETTINGS_MESSAGE",
cgiText(_("Unable to open cupsd.conf file:")));
/*
- * End of "$Id: admin.c 6361 2007-03-19 16:01:28Z mike $".
+ * End of "$Id: admin.c 6378 2007-03-21 07:18:18Z mike $".
*/
/*
- * "$Id: adminutil.c 6361 2007-03-19 16:01:28Z mike $"
+ * "$Id: adminutil.c 6378 2007-03-21 07:18:18Z mike $"
*
* Administration utility API definitions for the Common UNIX Printing
* System (CUPS).
* Local functions...
*/
+extern int _cupsAdminGetServerSettings(http_t *http,
+ int *num_settings,
+ cups_option_t **settings);
+extern int _cupsAdminSetServerSettings(http_t *http,
+ int num_settings,
+ cups_option_t *settings);
static int do_samba_command(const char *command,
const char *address,
const char *subcommand,
/*
- * End of "$Id: adminutil.c 6361 2007-03-19 16:01:28Z mike $".
+ * End of "$Id: adminutil.c 6378 2007-03-21 07:18:18Z mike $".
*/
/*
- * "$Id: adminutil.h 6268 2007-02-12 02:46:11Z mike $"
+ * "$Id: adminutil.h 6378 2007-03-21 07:18:18Z mike $"
*
* Administration utility API definitions for the Common UNIX Printing
* System (CUPS).
extern char *cupsAdminCreateWindowsPPD(http_t *http, const char *dest,
char *buffer, int bufsize);
-extern int _cupsAdminGetServerSettings(http_t *http,
- int *num_settings,
- cups_option_t **settings);
-extern int _cupsAdminSetServerSettings(http_t *http,
- int num_settings,
- cups_option_t *settings);
+extern int cupsAdminGetServerSettings(http_t *http,
+ int *num_settings,
+ cups_option_t **settings);
+extern int cupsAdminSetServerSettings(http_t *http,
+ int num_settings,
+ cups_option_t *settings);
# ifdef __cplusplus
#endif /* !_CUPS_ADMINUTIL_H_ */
/*
- * End of "$Id: adminutil.h 6268 2007-02-12 02:46:11Z mike $".
+ * End of "$Id: adminutil.h 6378 2007-03-21 07:18:18Z mike $".
*/
/*
- * "$Id: testadmin.c 5240 2006-03-07 21:55:29Z mike $"
+ * "$Id: testadmin.c 6379 2007-03-21 14:57:22Z mike $"
*
* Admin function test program for the Common UNIX Printing System (CUPS).
*
for (i = 1, num_settings = 0; i < argc; i ++)
num_settings = cupsParseOptions(argv[i], num_settings, &settings);
- if (_cupsAdminSetServerSettings(http, num_settings, settings))
+ if (cupsAdminSetServerSettings(http, num_settings, settings))
{
puts("New server settings:");
cupsFreeOptions(num_settings, settings);
* Get the current configuration...
*/
- if (_cupsAdminGetServerSettings(http, &num_settings, &settings))
+ if (cupsAdminGetServerSettings(http, &num_settings, &settings))
{
show_settings(num_settings, settings);
cupsFreeOptions(num_settings, settings);
/*
- * End of "$Id: testadmin.c 5240 2006-03-07 21:55:29Z mike $".
+ * End of "$Id: testadmin.c 6379 2007-03-21 14:57:22Z mike $".
*/
<p>The ppd-device-id attribute specifies the IEEE-1284 device ID
string for the device described by the PPD file.</p>
-<h4><a name="ppd-natural-scaling">ppd-natural-language (naturalLanguage)</a></h4>
-
-<p>The ppd-natural-language attribute specifies the language encoding
-of the PPD file (the LanguageVersion attribute in the PPD file). If the
-language is unknown or undefined then "en" (English) is assumed.
-
<h4><a name="ppd-make">ppd-make (text(127))</a></h4>
<p>The ppd-make attribute specifies the manufacturer of the printer
relative to the model directory. The forward slash (/) is used to
delineate directories.
+<h4><a name="ppd-natural-language">ppd-natural-language (naturalLanguage)</a></h4>
+
+<p>The ppd-natural-language attribute specifies the language encoding
+of the PPD file (the LanguageVersion attribute in the PPD file). If the
+language is unknown or undefined then "en" (English) is assumed.
+
+<h4><a name="ppd-product">ppd-product (text(127))</a></h4>
+
+<p>The ppd-product attribute specifies the Product attribute value in the PPD file.
+
+
<h3 class='title'><a name='PRINTER_ATTRIBUTES'>Printer Attributes</a></h3>
<h4><a name="auth-info-required">auth-info-required (1setOf type2 keyword)</a><span class="info">CUPS 1.3</span></h4>
/*
- * "$Id: gziptoany.c 4494 2005-02-18 02:18:11Z mike $"
+ * "$Id: gziptoany.c 6378 2007-03-21 07:18:18Z mike $"
*
- * GZIP pre-filter for the Common UNIX Printing System (CUPS).
+ * GZIP/raw pre-filter for the Common UNIX Printing System (CUPS).
*
- * Copyright 1993-2005 by Easy Software Products.
+ * Copyright 1993-2007 by Easy Software Products.
*
* These coded instructions, statements, and computer programs are the
* property of Easy Software Products and are protected by Federal
*
* Contents:
*
- * main() - Uncompress gzip'd files and send them to stdout...
+ * main() - Copy (and uncompress) files to stdout.
*/
/*
* Include necessary headers...
*/
+#include <cups/file.h>
#include <cups/string.h>
#include <stdlib.h>
#include <errno.h>
-#ifdef HAVE_LIBZ
-# include <zlib.h>
-#endif /* HAVE_LIBZ */
-
/*
- * 'main()' - Uncompress gzip'd files and send them to stdout...
+ * 'main()' - Copy (and uncompress) files to stdout.
*/
int /* O - Exit status */
main(int argc, /* I - Number of command-line arguments */
char *argv[]) /* I - Command-line arguments */
{
-#ifdef HAVE_LIBZ
- gzFile fp; /* GZIP'd file */
+ cups_file_t *fp; /* File */
char buffer[8192]; /* Data buffer */
int bytes; /* Number of bytes read/written */
int copies; /* Number of copies */
- const char *content_type; /* Content type for file... */
/*
}
/*
- * Get the copy count; if the MIME type is "application/vnd.cups-raw" then
- * make copies since the file is going straight to a backend...
+ * Get the copy count; if we have no final content type, this is a
+ * raw queue or raw print file, so we need to make copies...
*/
- if ((content_type = getenv("CONTENT_TYPE")) != NULL &&
- !strcasecmp(content_type, "application/vnd.cups-raw"))
+ if (!getenv("FINAL_CONTENT_TYPE"))
copies = atoi(argv[4]);
else
copies = 1;
/*
- * Open the gzip file...
+ * Open the file...
*/
- if ((fp = gzopen(argv[6], "rb")) == NULL)
+ if ((fp = cupsFileOpen(argv[6], "r")) == NULL)
{
- fprintf(stderr, "ERROR: Unable to open GZIP file: %s\n", strerror(errno));
+ fprintf(stderr, "ERROR: Unable to open file \"%s\": %s\n", argv[6],
+ strerror(errno));
return (1);
}
/*
- * Copy the gzip file to stdout...
+ * Copy the file to stdout...
*/
setbuf(stdout, NULL);
while (copies > 0)
{
- gzrewind(fp);
+ cupsFileRewind(fp);
- while ((bytes = gzread(fp, buffer, sizeof(buffer))) > 0)
+ while ((bytes = cupsFileRead(fp, buffer, sizeof(buffer))) > 0)
if (fwrite(buffer, 1, bytes, stdout) < bytes)
{
- fprintf(stderr, "ERROR: Unable to write uncompressed document data: %s\n",
+ fprintf(stderr,
+ "ERROR: Unable to write uncompressed document data: %s\n",
strerror(ferror(stdout)));
- gzclose(fp);
+ cupsFileClose(fp);
return (1);
}
* Close the file and return...
*/
- gzclose(fp);
+ cupsFileClose(fp);
return (0);
-#else
- fputs("INFO: Hint: recompile CUPS with ZLIB.\n", stderr);
- fputs("ERROR: GZIP compression support not compiled in!\n", stderr);
- return (1);
-#endif /* HAVE_LIBZ */
}
/*
- * End of "$Id: gziptoany.c 4494 2005-02-18 02:18:11Z mike $".
+ * End of "$Id: gziptoany.c 6378 2007-03-21 07:18:18Z mike $".
*/
/*
- * "$Id: interpret.c 6281 2007-02-14 16:32:42Z mike $"
+ * "$Id: interpret.c 6371 2007-03-20 23:18:01Z mike $"
*
* PPD command interpreter for the Common UNIX Printing System (CUPS).
*
{
float sc = atof(val);
- if (sc >= 0.9 && sc <= 1.1)
+ if (sc >= 0.5 && sc <= 2.0)
h->cupsBorderlessScalingFactor = sc;
}
/*
- * End of "$Id: interpret.c 6281 2007-02-14 16:32:42Z mike $".
+ * End of "$Id: interpret.c 6371 2007-03-20 23:18:01Z mike $".
*/
/*
- * "$Id: client.c 6361 2007-03-19 16:01:28Z mike $"
+ * "$Id: client.c 6383 2007-03-21 20:01:20Z mike $"
*
* Client routines for the Common UNIX Printing System (CUPS) scheduler.
*
* cupsdSendHeader() - Send an HTTP request.
* cupsdUpdateCGI() - Read status messages from CGI scripts and programs.
* cupsdWriteClient() - Write data to a client as needed.
- * cupsdWritePipe() - Flag that data is available on the CGI pipe.
* check_if_modified() - Decode an "If-Modified-Since" line.
* encrypt_client() - Enable encryption for the client...
* get_cdsa_certificate() - Convert a keychain name into the CFArrayRef
* make_certificate() - Make a self-signed SSL/TLS certificate.
* pipe_command() - Pipe the output of a command to the remote client.
* write_file() - Send a file via HTTP.
+ * write_pipe() - Flag that data is available on the CGI pipe.
*/
/*
static int write_file(cupsd_client_t *con, http_status_t code,
char *filename, char *type,
struct stat *filestats);
+static void write_pipe(cupsd_client_t *con);
/*
cupsdLogMessage(CUPSD_LOG_ERROR,
"Bad request line \"%s\" from %s!", line,
con->http.hostname);
- cupsdSendError(con, HTTP_BAD_REQUEST);
+ cupsdSendError(con, HTTP_BAD_REQUEST, AUTH_NONE);
cupsdCloseClient(con);
return;
case 2 :
cupsdLogMessage(CUPSD_LOG_ERROR,
"Bad request line \"%s\" from %s!", line,
con->http.hostname);
- cupsdSendError(con, HTTP_BAD_REQUEST);
+ cupsdSendError(con, HTTP_BAD_REQUEST, AUTH_NONE);
cupsdCloseClient(con);
return;
}
}
else
{
- cupsdSendError(con, HTTP_NOT_SUPPORTED);
+ cupsdSendError(con, HTTP_NOT_SUPPORTED, AUTH_NONE);
cupsdCloseClient(con);
return;
}
cupsdLogMessage(CUPSD_LOG_ERROR, "Bad URI \"%s\" in request!",
con->uri);
- cupsdSendError(con, HTTP_METHOD_NOT_ALLOWED);
+ cupsdSendError(con, HTTP_METHOD_NOT_ALLOWED, AUTH_NONE);
cupsdCloseClient(con);
return;
}
else
{
cupsdLogMessage(CUPSD_LOG_ERROR, "Bad operation \"%s\"!", operation);
- cupsdSendError(con, HTTP_BAD_REQUEST);
+ cupsdSendError(con, HTTP_BAD_REQUEST, AUTH_NONE);
cupsdCloseClient(con);
return;
}
if (status != HTTP_OK && status != HTTP_CONTINUE)
{
- cupsdSendError(con, HTTP_BAD_REQUEST);
+ cupsdSendError(con, HTTP_BAD_REQUEST, AUTH_NONE);
cupsdCloseClient(con);
return;
}
* HTTP/1.1 and higher require the "Host:" field...
*/
- if (!cupsdSendError(con, HTTP_BAD_REQUEST))
+ if (!cupsdSendError(con, HTTP_BAD_REQUEST, AUTH_NONE))
{
cupsdCloseClient(con);
return;
if (con->best && con->best->type != AUTH_NONE)
{
- if (!cupsdSendHeader(con, HTTP_UNAUTHORIZED, NULL))
+ if (!cupsdSendHeader(con, HTTP_UNAUTHORIZED, NULL, AUTH_NONE))
{
cupsdCloseClient(con);
return;
* Do encryption stuff...
*/
- if (!cupsdSendHeader(con, HTTP_SWITCHING_PROTOCOLS, NULL))
+ if (!cupsdSendHeader(con, HTTP_SWITCHING_PROTOCOLS, NULL, AUTH_NONE))
{
cupsdCloseClient(con);
return;
return;
}
#else
- if (!cupsdSendError(con, HTTP_NOT_IMPLEMENTED))
+ if (!cupsdSendError(con, HTTP_NOT_IMPLEMENTED, AUTH_NONE))
{
cupsdCloseClient(con);
return;
#endif /* HAVE_SSL */
}
- if (!cupsdSendHeader(con, HTTP_OK, NULL))
+ if (!cupsdSendHeader(con, HTTP_OK, NULL, AUTH_NONE))
{
cupsdCloseClient(con);
return;
* Protect against malicious users!
*/
- if (!cupsdSendError(con, HTTP_FORBIDDEN))
+ if (!cupsdSendError(con, HTTP_FORBIDDEN, AUTH_NONE))
{
cupsdCloseClient(con);
return;
* Do encryption stuff...
*/
- if (!cupsdSendHeader(con, HTTP_SWITCHING_PROTOCOLS, NULL))
+ if (!cupsdSendHeader(con, HTTP_SWITCHING_PROTOCOLS, NULL, AUTH_NONE))
{
cupsdCloseClient(con);
return;
return;
}
#else
- if (!cupsdSendError(con, HTTP_NOT_IMPLEMENTED))
+ if (!cupsdSendError(con, HTTP_NOT_IMPLEMENTED, AUTH_NONE))
{
cupsdCloseClient(con);
return;
cupsdLogMessage(CUPSD_LOG_DEBUG2,
"cupsdReadClient: Unauthorized request for %s...\n",
con->uri);
- cupsdSendError(con, status);
+ cupsdSendError(con, status, AUTH_NONE);
cupsdCloseClient(con);
return;
}
* Send 100-continue header...
*/
- if (!cupsdSendHeader(con, HTTP_CONTINUE, NULL))
+ if (!cupsdSendHeader(con, HTTP_CONTINUE, NULL, AUTH_NONE))
{
cupsdCloseClient(con);
return;
* Send 417-expectation-failed header...
*/
- if (!cupsdSendHeader(con, HTTP_EXPECTATION_FAILED, NULL))
+ if (!cupsdSendHeader(con, HTTP_EXPECTATION_FAILED, NULL, AUTH_NONE))
{
cupsdCloseClient(con);
return;
snprintf(con->uri, sizeof(con->uri), "/ppd/%s.ppd", p->name);
else
{
- if (!cupsdSendError(con, HTTP_NOT_FOUND))
+ if (!cupsdSendError(con, HTTP_NOT_FOUND, AUTH_NONE))
{
cupsdCloseClient(con);
return;
if (!cupsdSendCommand(con, con->command, con->options, 0))
{
- if (!cupsdSendError(con, HTTP_NOT_FOUND))
+ if (!cupsdSendError(con, HTTP_NOT_FOUND, AUTH_NONE))
{
cupsdCloseClient(con);
return;
* /admin/conf...
*/
- if (!cupsdSendError(con, HTTP_FORBIDDEN))
+ if (!cupsdSendError(con, HTTP_FORBIDDEN, AUTH_NONE))
{
cupsdCloseClient(con);
return;
if ((filename = get_file(con, &filestats, buf,
sizeof(buf))) == NULL)
{
- if (!cupsdSendError(con, HTTP_NOT_FOUND))
+ if (!cupsdSendError(con, HTTP_NOT_FOUND, AUTH_NONE))
{
cupsdCloseClient(con);
return;
if (!cupsdSendCommand(con, con->command, con->options, 0))
{
- if (!cupsdSendError(con, HTTP_NOT_FOUND))
+ if (!cupsdSendError(con, HTTP_NOT_FOUND, AUTH_NONE))
{
cupsdCloseClient(con);
return;
if (!check_if_modified(con, &filestats))
{
- if (!cupsdSendError(con, HTTP_NOT_MODIFIED))
+ if (!cupsdSendError(con, HTTP_NOT_MODIFIED, AUTH_NONE))
{
cupsdCloseClient(con);
return;
* Request too large...
*/
- if (!cupsdSendError(con, HTTP_REQUEST_TOO_LARGE))
+ if (!cupsdSendError(con, HTTP_REQUEST_TOO_LARGE, AUTH_NONE))
{
cupsdCloseClient(con);
return;
* Negative content lengths are invalid!
*/
- if (!cupsdSendError(con, HTTP_BAD_REQUEST))
+ if (!cupsdSendError(con, HTTP_BAD_REQUEST, AUTH_NONE))
{
cupsdCloseClient(con);
return;
if ((filename = get_file(con, &filestats, buf,
sizeof(buf))) == NULL)
{
- if (!cupsdSendError(con, HTTP_NOT_FOUND))
+ if (!cupsdSendError(con, HTTP_NOT_FOUND, AUTH_NONE))
{
cupsdCloseClient(con);
return;
* Only POST to CGI's...
*/
- if (!cupsdSendError(con, HTTP_UNAUTHORIZED))
+ if (!cupsdSendError(con, HTTP_UNAUTHORIZED, AUTH_NONE))
{
cupsdCloseClient(con);
return;
* /admin/conf...
*/
- if (!cupsdSendError(con, HTTP_FORBIDDEN))
+ if (!cupsdSendError(con, HTTP_FORBIDDEN, AUTH_NONE))
{
cupsdCloseClient(con);
return;
* Request too large...
*/
- if (!cupsdSendError(con, HTTP_REQUEST_TOO_LARGE))
+ if (!cupsdSendError(con, HTTP_REQUEST_TOO_LARGE, AUTH_NONE))
{
cupsdCloseClient(con);
return;
* Negative content lengths are invalid!
*/
- if (!cupsdSendError(con, HTTP_BAD_REQUEST))
+ if (!cupsdSendError(con, HTTP_BAD_REQUEST, AUTH_NONE))
{
cupsdCloseClient(con);
return;
if (con->file < 0)
{
- if (!cupsdSendError(con, HTTP_REQUEST_TOO_LARGE))
+ if (!cupsdSendError(con, HTTP_REQUEST_TOO_LARGE, AUTH_NONE))
{
cupsdCloseClient(con);
return;
case HTTP_DELETE :
case HTTP_TRACE :
- cupsdSendError(con, HTTP_NOT_IMPLEMENTED);
+ cupsdSendError(con, HTTP_NOT_IMPLEMENTED, AUTH_NONE);
cupsdCloseClient(con);
return;
snprintf(con->uri, sizeof(con->uri), "/ppd/%s.ppd", p->name);
else
{
- if (!cupsdSendError(con, HTTP_NOT_FOUND))
+ if (!cupsdSendError(con, HTTP_NOT_FOUND, AUTH_NONE))
{
cupsdCloseClient(con);
return;
* CGI output...
*/
- if (!cupsdSendHeader(con, HTTP_OK, "text/html"))
+ if (!cupsdSendHeader(con, HTTP_OK, "text/html", AUTH_NONE))
{
cupsdCloseClient(con);
return;
* /admin/conf...
*/
- if (!cupsdSendError(con, HTTP_FORBIDDEN))
+ if (!cupsdSendError(con, HTTP_FORBIDDEN, AUTH_NONE))
{
cupsdCloseClient(con);
return;
else if ((filename = get_file(con, &filestats, buf,
sizeof(buf))) == NULL)
{
- if (!cupsdSendHeader(con, HTTP_NOT_FOUND, "text/html"))
+ if (!cupsdSendHeader(con, HTTP_NOT_FOUND, "text/html", AUTH_NONE))
{
cupsdCloseClient(con);
return;
}
else if (!check_if_modified(con, &filestats))
{
- if (!cupsdSendError(con, HTTP_NOT_MODIFIED))
+ if (!cupsdSendError(con, HTTP_NOT_MODIFIED, AUTH_NONE))
{
cupsdCloseClient(con);
return;
else
snprintf(line, sizeof(line), "%s/%s", type->super, type->type);
- if (!cupsdSendHeader(con, HTTP_OK, line))
+ if (!cupsdSendHeader(con, HTTP_OK, line, AUTH_NONE))
{
cupsdCloseClient(con);
return;
unlink(con->filename);
cupsdClearString(&con->filename);
- if (!cupsdSendError(con, HTTP_REQUEST_TOO_LARGE))
+ if (!cupsdSendError(con, HTTP_REQUEST_TOO_LARGE, AUTH_NONE))
{
cupsdCloseClient(con);
return;
unlink(con->filename);
cupsdClearString(&con->filename);
- if (!cupsdSendError(con, HTTP_REQUEST_TOO_LARGE))
+ if (!cupsdSendError(con, HTTP_REQUEST_TOO_LARGE, AUTH_NONE))
{
cupsdCloseClient(con);
return;
* Return the status to the client...
*/
- if (!cupsdSendError(con, status))
+ if (!cupsdSendError(con, status, AUTH_NONE))
{
cupsdCloseClient(con);
return;
"cupsdReadClient: %d IPP Read Error!",
con->http.fd);
- cupsdSendError(con, HTTP_BAD_REQUEST);
+ cupsdSendError(con, HTTP_BAD_REQUEST, AUTH_NONE);
cupsdCloseClient(con);
return;
}
{
if (con->http.state == HTTP_POST_SEND)
{
- cupsdSendError(con, HTTP_BAD_REQUEST);
+ cupsdSendError(con, HTTP_BAD_REQUEST, AUTH_NONE);
cupsdCloseClient(con);
return;
}
if (con->file < 0)
{
- if (!cupsdSendError(con, HTTP_REQUEST_TOO_LARGE))
+ if (!cupsdSendError(con, HTTP_REQUEST_TOO_LARGE, AUTH_NONE))
{
cupsdCloseClient(con);
return;
unlink(con->filename);
cupsdClearString(&con->filename);
- if (!cupsdSendError(con, HTTP_REQUEST_TOO_LARGE))
+ if (!cupsdSendError(con, HTTP_REQUEST_TOO_LARGE, AUTH_NONE))
{
cupsdCloseClient(con);
return;
con->request = NULL;
}
- if (!cupsdSendError(con, HTTP_REQUEST_TOO_LARGE))
+ if (!cupsdSendError(con, HTTP_REQUEST_TOO_LARGE, AUTH_NONE))
{
cupsdCloseClient(con);
return;
{
if (!cupsdSendCommand(con, con->command, con->options, 0))
{
- if (!cupsdSendError(con, HTTP_NOT_FOUND))
+ if (!cupsdSendError(con, HTTP_NOT_FOUND, AUTH_NONE))
{
cupsdCloseClient(con);
return;
fcntl(con->file, F_SETFD, fcntl(con->file, F_GETFD) | FD_CLOEXEC);
- cupsdAddSelect(con->file, (cupsd_selfunc_t)cupsdWritePipe, NULL, con);
+ cupsdAddSelect(con->file, (cupsd_selfunc_t)write_pipe, NULL, con);
con->sent_header = 0;
con->file_ready = 0;
int /* O - 1 if successful, 0 otherwise */
cupsdSendError(cupsd_client_t *con, /* I - Connection */
- http_status_t code) /* I - Error code */
+ http_status_t code, /* I - Error code */
+ int auth_type)/* I - Authentication type */
{
#ifdef HAVE_SSL
/*
* 400 or 500 series, make sure the message contains some text, too!
*/
- if (!cupsdSendHeader(con, code, NULL))
+ if (!cupsdSendHeader(con, code, NULL, auth_type))
return (0);
#ifdef HAVE_SSL
*/
int /* O - 1 on success, 0 on failure */
-cupsdSendHeader(cupsd_client_t *con, /* I - Client to send to */
- http_status_t code, /* I - HTTP status code */
- char *type) /* I - MIME type of document */
+cupsdSendHeader(
+ cupsd_client_t *con, /* I - Client to send to */
+ http_status_t code, /* I - HTTP status code */
+ char *type, /* I - MIME type of document */
+ int auth_type) /* I - Type of authentication */
{
char auth_str[1024]; /* Authorization string */
if (code == HTTP_UNAUTHORIZED)
{
- int auth_type; /* Authentication type */
-
-
- if (!con->best || con->best->type == AUTH_NONE)
- auth_type = DefaultAuthType;
- else
- auth_type = con->best->type;
+ if (auth_type == AUTH_NONE)
+ {
+ if (!con->best || con->best->type == AUTH_NONE)
+ auth_type = DefaultAuthType;
+ else
+ auth_type = con->best->type;
+ }
auth_str[0] = '\0';
* Make sure we select on the CGI output...
*/
- cupsdAddSelect(con->file, (cupsd_selfunc_t)cupsdWritePipe, NULL, con);
+ cupsdAddSelect(con->file, (cupsd_selfunc_t)write_pipe, NULL, con);
if (!con->file_ready)
{
if (!strncasecmp(buf, "Location:", 9))
{
- cupsdSendHeader(con, HTTP_SEE_OTHER, NULL);
+ cupsdSendHeader(con, HTTP_SEE_OTHER, NULL, AUTH_NONE);
con->sent_header = 2;
if (httpPrintf(HTTP(con), "Content-Length: 0\r\n") < 0)
}
else if (!strncasecmp(buf, "Status:", 7))
{
- cupsdSendError(con, (http_status_t)atoi(buf + 7));
+ cupsdSendError(con, (http_status_t)atoi(buf + 7), AUTH_NONE);
con->sent_header = 2;
}
else
{
- cupsdSendHeader(con, HTTP_OK, NULL);
+ cupsdSendHeader(con, HTTP_OK, NULL, AUTH_NONE);
con->sent_header = 1;
if (con->http.version == HTTP_1_1)
}
-/*
- * 'cupsdWritePipe()' - Flag that data is available on the CGI pipe.
- */
-
-void
-cupsdWritePipe(cupsd_client_t *con) /* I - Client connection */
-{
- cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdWritePipe: CGI output on fd %d...",
- con->file);
-
- con->file_ready = 1;
-
- cupsdRemoveSelect(con->file);
- cupsdAddSelect(con->http.fd, NULL, (cupsd_selfunc_t)cupsdWriteClient, con);
-}
-
-
/*
* 'check_if_modified()' - Decode an "If-Modified-Since" line.
*/
con->pipe_pid = 0;
- if (!cupsdSendHeader(con, code, type))
+ if (!cupsdSendHeader(con, code, type, AUTH_NONE))
return (0);
if (httpPrintf(HTTP(con), "Last-Modified: %s\r\n",
/*
- * End of "$Id: client.c 6361 2007-03-19 16:01:28Z mike $".
+ * 'write_pipe()' - Flag that data is available on the CGI pipe.
+ */
+
+static void
+write_pipe(cupsd_client_t *con) /* I - Client connection */
+{
+ cupsdLogMessage(CUPSD_LOG_DEBUG2, "write_pipe: CGI output on fd %d...",
+ con->file);
+
+ con->file_ready = 1;
+
+ cupsdRemoveSelect(con->file);
+ cupsdAddSelect(con->http.fd, NULL, (cupsd_selfunc_t)cupsdWriteClient, con);
+}
+
+
+/*
+ * End of "$Id: client.c 6383 2007-03-21 20:01:20Z mike $".
*/
/*
- * "$Id: client.h 6253 2007-02-10 18:48:40Z mike $"
+ * "$Id: client.h 6383 2007-03-21 20:01:20Z mike $"
*
* Client definitions for the Common UNIX Printing System (CUPS) scheduler.
*
extern void cupsdResumeListening(void);
extern int cupsdSendCommand(cupsd_client_t *con, char *command,
char *options, int root);
-extern int cupsdSendError(cupsd_client_t *con, http_status_t code);
+extern int cupsdSendError(cupsd_client_t *con, http_status_t code,
+ int auth_type);
extern int cupsdSendHeader(cupsd_client_t *con, http_status_t code,
- char *type);
+ char *type, int auth_type);
extern void cupsdShutdownClient(cupsd_client_t *con);
extern void cupsdStartListening(void);
extern void cupsdStopListening(void);
extern void cupsdUpdateCGI(void);
extern void cupsdWriteClient(cupsd_client_t *con);
-extern void cupsdWritePipe(cupsd_client_t *con);
/*
- * End of "$Id: client.h 6253 2007-02-10 18:48:40Z mike $".
+ * End of "$Id: client.h 6383 2007-03-21 20:01:20Z mike $".
*/
/*
- * "$Id: cups-driverd.c 6363 2007-03-19 20:48:49Z mike $"
+ * "$Id: cups-driverd.c 6377 2007-03-21 07:17:11Z mike $"
*
* PPD/driver support for the Common UNIX Printing System (CUPS).
*
* in CUPS_DATADIR/model and dynamically generated PPD files using
* the driver helper programs in CUPS_SERVERBIN/driver.
*
- * Copyright 1997-2006 by Easy Software Products.
+ * Copyright 1997-2007 by Easy Software Products.
*
* These coded instructions, statements, and computer programs are the
* property of Easy Software Products and are protected by Federal
size_t size; /* Size in bytes */
char name[512 - sizeof(time_t) - sizeof(size_t)],
/* PPD name */
- natural_language[128], /* Natural language(s) */
+ natural_language[6], /* LanguageVersion */
+ product[122], /* Product */
make[128], /* Manufacturer */
- make_and_model[128], /* Make and model */
+ make_and_model[128], /* NickName/ModelName */
device_id[128]; /* IEEE 1284 Device ID */
} ppd_rec_t;
*/
static ppd_info_t *add_ppd(const char *name, const char *natural_language,
- const char *make, const char *make_and_model,
- const char *device_id, time_t mtime, size_t size);
+ const char *make, const char *make_and_model,
+ const char *device_id, const char *product,
+ time_t mtime, size_t size);
static int cat_ppd(const char *name);
static int compare_names(const ppd_info_t *p0,
const ppd_info_t *p1);
add_ppd(const char *name, /* I - PPD name */
const char *natural_language, /* I - Language(s) */
const char *make, /* I - Manufacturer */
- const char *make_and_model, /* I - NickName */
+ const char *make_and_model, /* I - NickName/ModelName */
const char *device_id, /* I - 1284DeviceID */
+ const char *product, /* I - Product */
time_t mtime, /* I - Modification time */
size_t size) /* I - File size */
{
strlcpy(ppd->record.name, name, sizeof(ppd->record.name));
strlcpy(ppd->record.natural_language, natural_language,
sizeof(ppd->record.natural_language));
+ strlcpy(ppd->record.product, product, sizeof(ppd->record.product));
strlcpy(ppd->record.make, make, sizeof(ppd->record.make));
strlcpy(ppd->record.make_and_model, make_and_model,
sizeof(ppd->record.make_and_model));
send_make, /* Send ppd-make attribute? */
send_make_and_model, /* Send ppd-make-and-model attribute? */
send_name, /* Send ppd-name attribute? */
- send_device_id; /* Send ppd-device-id attribute? */
+ send_device_id, /* Send ppd-device-id attribute? */
+ send_product; /* Send ppd-product attribute? */
fprintf(stderr, "DEBUG2: [cups-driverd] list_ppds(request_id=%d, limit=%d, opt=\"%s\"\n",
* Add the raw driver...
*/
- add_ppd("raw", "en", "Raw", "Raw Queue", "", 0, 0);
+ add_ppd("raw", "en", "Raw", "Raw Queue", "", "", 0, 0);
/*
* Sort the PPDs by make and model...
send_make_and_model = 1;
send_natural_language = 1;
send_device_id = 1;
+ send_product = 1;
}
else
{
send_make_and_model = strstr(requested, "ppd-make-and-model") != NULL;
send_natural_language = strstr(requested, "ppd-natural-language") != NULL;
send_device_id = strstr(requested, "ppd-device-id") != NULL;
+ send_product = strstr(requested, "ppd-product") != NULL;
}
puts("Content-Type: application/ipp\n");
cupsdSendIPPString(IPP_TAG_TEXT, "ppd-device-id",
ppd->record.device_id);
+ if (send_product)
+ cupsdSendIPPString(IPP_TAG_TEXT, "ppd-product",
+ ppd->record.product);
+
/*
* If we have only requested the ppd-make attribute, then skip
* the remaining PPDs with this make...
make_model[256], /* Make and Model */
model_name[256], /* ModelName */
nick_name[256], /* NickName */
- device_id[256]; /* 1284DeviceID */
+ device_id[256], /* 1284DeviceID */
+ product[256]; /* Product */
+ cups_array_t *products; /* Array of product strings */
ppd_info_t *ppd, /* New PPD file */
key; /* Search key */
int new_ppd; /* Is this a new PPD? */
* Now read until we get the NickName field...
*/
+ products = cupsArrayNew(NULL, NULL);
+
model_name[0] = '\0';
nick_name[0] = '\0';
manufacturer[0] = '\0';
sscanf(line, "%*[^\"]\"%255[^\"]", nick_name);
else if (!strncasecmp(line, "*1284DeviceID:", 14))
sscanf(line, "%*[^\"]\"%255[^\"]", device_id);
+ else if (!strncasecmp(line, "*Product:", 9))
+ {
+ sscanf(line, "%*[^\"]\"(%255[^)]", product);
+ cupsArrayAdd(products, strdup(product));
+ }
else if (!strncmp(line, "*OpenUI", 7))
{
/*
* before the first OpenUI...
*/
- if (model_name[0] || nick_name[0])
+ if ((model_name[0] || nick_name[0]) && cupsArrayCount(products) > 0)
break;
}
}
while (isspace(make_model[0] & 255))
_cups_strcpy(make_model, make_model + 1);
- if (!make_model[0])
- continue; /* Nope... */
+ if (!make_model[0] || cupsArrayCount(products) == 0)
+ {
+ /*
+ * We don't have all the info needed, so skip this file...
+ */
+
+ if (!make_model[0])
+ fprintf(stderr, "WARNING: Missing NickName and ModelName in %s!\n",
+ filename);
+
+ if (cupsArrayCount(products) == 0)
+ fprintf(stderr, "WARNING: Missing Product in %s!\n", filename);
+
+ for (ptr = (char *)cupsArrayFirst(products);
+ ptr;
+ ptr = (char *)cupsArrayNext(products))
+ free(ptr);
+
+ cupsArrayDelete(products);
+
+ continue;
+ }
/*
* See if we got a manufacturer...
fprintf(stderr, "DEBUG: [cups-driverd] Adding ppd \"%s\"...\n", name);
+ /* TODO: Support multiple Products... */
if (!add_ppd(name, lang_version, manufacturer, make_model, device_id,
+ (char *)cupsArrayFirst(products),
dent->fileinfo.st_mtime, dent->fileinfo.st_size))
{
cupsDirClose(dir);
sizeof(ppd->record.make_and_model));
strlcpy(ppd->record.natural_language, lang_version,
sizeof(ppd->record.natural_language));
+ strlcpy(ppd->record.product, (char *)cupsArrayFirst(products),
+ sizeof(ppd->record.product));
strlcpy(ppd->record.device_id, device_id, sizeof(ppd->record.device_id));
}
+ /*
+ * Free products...
+ */
+
+ for (ptr = (char *)cupsArrayFirst(products);
+ ptr;
+ ptr = (char *)cupsArrayNext(products))
+ free(ptr);
+
+ cupsArrayDelete(products);
+
ChangedPPD = 1;
}
natural_language[128], /* ppd-natural-language */
make[128], /* ppd-make */
make_and_model[256], /* ppd-make-and-model */
- device_id[256]; /* ppd-device-id */
+ device_id[256], /* ppd-device-id */
+ product[256]; /* ppd-product */
/*
/*
* Each line is of the form:
*
- * \"ppd-name\" ppd-natural-language "ppd-make" "ppd-make-and-model"
+ * "ppd-name" ppd-natural-language "ppd-make" "ppd-make-and-model" \
+ * "ppd-device-id" "ppd-product"
*/
device_id[0] = '\0';
+ product[0] = '\0';
if (sscanf(line, "\"%511[^\"]\"%127s%*[ \t]\"%127[^\"]\""
- "%*[ \t]\"%256[^\"]\"%*[ \t]\"%256[^\"]\"",
+ "%*[ \t]\"%256[^\"]\"%*[ \t]\"%256[^\"]\""
+ "%*[ \t]\"%256[^\"]\"",
name, natural_language, make, make_and_model,
- device_id) < 4)
+ device_id, product) < 4)
{
/*
* Bad format; strip trailing newline and write an error message.
*/
if (!add_ppd(name, natural_language, make, make_and_model, device_id,
- 0, 0))
+ product, 0, 0))
{
cupsDirClose(dir);
return (0);
/*
- * End of "$Id: cups-driverd.c 6363 2007-03-19 20:48:49Z mike $".
+ * End of "$Id: cups-driverd.c 6377 2007-03-21 07:17:11Z mike $".
*/
/*
- * "$Id: cupsd.h 6365 2007-03-19 20:56:57Z mike $"
+ * "$Id: cupsd.h 6376 2007-03-21 06:39:10Z mike $"
*
* Main header file for the Common UNIX Printing System (CUPS) scheduler.
*
- * Copyright 1997-2006 by Easy Software Products, all rights reserved.
+ * Copyright 1997-2007 by Easy Software Products, all rights reserved.
*
* These coded instructions, statements, and computer programs are the
* property of Easy Software Products and are protected by Federal
extern int cupsdAddSelect(int fd, cupsd_selfunc_t read_cb,
cupsd_selfunc_t write_cb, void *data);
extern int cupsdDoSelect(long timeout);
+#ifdef CUPSD_IS_SELECTING
extern int cupsdIsSelecting(int fd);
+#endif /* CUPSD_IS_SELECTING */
extern void cupsdRemoveSelect(int fd);
extern void cupsdStartSelect(void);
extern void cupsdStopSelect(void);
/*
- * End of "$Id: cupsd.h 6365 2007-03-19 20:56:57Z mike $".
+ * End of "$Id: cupsd.h 6376 2007-03-21 06:39:10Z mike $".
*/
/*
- * "$Id: dirsvc.c 6354 2007-03-19 06:16:32Z mike $"
+ * "$Id: dirsvc.c 6376 2007-03-21 06:39:10Z mike $"
*
* Directory services routines for the Common UNIX Printing System (CUPS).
*
* cupsdStopBrowsing() - Stop sending and receiving broadcast
* information.
* cupsdStopPolling() - Stop polling servers as needed.
- * cupsdUpdateCUPSBrowse() - Update the browse lists using the CUPS
- * protocol.
* cupsdUpdateDNSSDBrowse() - Handle DNS-SD queries.
* cupsdUpdateLDAPBrowse() - Scan for new printers via LDAP...
- * cupsdUpdatePolling() - Read status messages from the poll daemons.
* cupsdUpdateSLPBrowse() - Get browsing information via SLP.
* dnssdBuildTxtRecord() - Build a TXT record from printer info.
* dnssdDeregisterPrinter() - Stop sending broadcast information for a
* slp_get_attr() - Get an attribute from an SLP registration.
* slp_reg_callback() - Empty SLPRegReport.
* slp_url_callback() - SLP service url callback
+ * update_cups_browse() - Update the browse lists using the CUPS
+ * protocol.
+ * update_polling() - Read status messages from the poll daemons.
*/
/*
#ifdef HAVE_LIBSLP
static void send_slp_browse(cupsd_printer_t *p);
#endif /* HAVE_LIBSLP */
+static void update_cups_browse(void);
+static void update_polling(void);
+
#ifdef HAVE_OPENLDAP
static const char * const ldap_attrs[] =/* CUPS LDAP attributes */
* We only listen if we want remote printers...
*/
- cupsdAddSelect(BrowseSocket, (cupsd_selfunc_t)cupsdUpdateCUPSBrowse,
+ cupsdAddSelect(BrowseSocket, (cupsd_selfunc_t)update_cups_browse,
NULL, NULL);
}
}
* Finally, add the pipe to the input selection set...
*/
- cupsdAddSelect(PollPipe, (cupsd_selfunc_t)cupsdUpdatePolling, NULL, NULL);
+ cupsdAddSelect(PollPipe, (cupsd_selfunc_t)update_polling, NULL, NULL);
}
}
+#ifdef HAVE_DNSSD
/*
- * 'cupsdUpdateCUPSBrowse()' - Update the browse lists using the CUPS protocol.
+ * 'cupsdUpdateDNSSDBrowse()' - Handle DNS-SD queries.
*/
void
-cupsdUpdateCUPSBrowse(void)
+cupsdUpdateDNSSDBrowse(
+ cupsd_printer_t *p) /* I - Printer being queried */
{
- int i; /* Looping var */
- int auth; /* Authorization status */
- int len; /* Length of name string */
- int bytes; /* Number of bytes left */
- char packet[1541], /* Broadcast packet */
- *pptr; /* Pointer into packet */
- socklen_t srclen; /* Length of source address */
- http_addr_t srcaddr; /* Source address */
- char srcname[1024]; /* Source hostname */
- unsigned address[4]; /* Source address */
- unsigned type; /* Printer type */
- unsigned state; /* Printer state */
- char uri[HTTP_MAX_URI], /* Printer URI */
- host[HTTP_MAX_URI], /* Host portion of URI */
- resource[HTTP_MAX_URI], /* Resource portion of URI */
- info[IPP_MAX_NAME], /* Information string */
- location[IPP_MAX_NAME], /* Location string */
- make_model[IPP_MAX_NAME];/* Make and model string */
- int num_attrs; /* Number of attributes */
- cups_option_t *attrs; /* Attributes */
-
+ DNSServiceErrorType sdErr; /* Service discovery error */
- /*
- * Read a packet from the browse socket...
- */
- srclen = sizeof(srcaddr);
- if ((bytes = recvfrom(BrowseSocket, packet, sizeof(packet) - 1, 0,
- (struct sockaddr *)&srcaddr, &srclen)) < 0)
+ if ((sdErr = DNSServiceProcessResult(p->dnssd_ipp_ref))
+ != kDNSServiceErr_NoError)
{
- /*
- * "Connection refused" is returned under Linux if the destination port
- * or address is unreachable from a previous sendto(); check for the
- * error here and ignore it for now...
- */
+ cupsdLogMessage(CUPSD_LOG_ERROR,
+ "DNS Service Discovery registration error %d for \"%s\"!",
+ sdErr, p->name);
+ cupsdRemoveSelect(p->dnssd_ipp_fd);
+ DNSServiceRefDeallocate(p->dnssd_ipp_ref);
- if (errno != ECONNREFUSED && errno != EAGAIN)
- {
- cupsdLogMessage(CUPSD_LOG_ERROR, "Browse recv failed - %s.",
- strerror(errno));
- cupsdLogMessage(CUPSD_LOG_ERROR, "Browsing turned off.");
+ p->dnssd_ipp_ref = NULL;
+ p->dnssd_ipp_fd = -1;
+ }
+}
+#endif /* HAVE_DNSSD */
- cupsdStopBrowsing();
- Browsing = 0;
- }
- return;
- }
+#ifdef HAVE_OPENLDAP
+/*
+ * 'cupsdUpdateLDAPBrowse()' - Scan for new printers via LDAP...
+ */
+
+void
+cupsdUpdateLDAPBrowse(void)
+{
+ char uri[HTTP_MAX_URI], /* Printer URI */
+ host[HTTP_MAX_URI], /* Hostname */
+ resource[HTTP_MAX_URI], /* Resource path */
+ location[1024], /* Printer location */
+ info[1024], /* Printer information */
+ make_model[1024], /* Printer make and model */
+ **value; /* Holds the returned data from LDAP */
+ int type; /* Printer type */
+ int rc; /* LDAP status */
+ int limit; /* Size limit */
+ LDAPMessage *res, /* LDAP search results */
+ *e; /* Current entry from search */
- packet[bytes] = '\0';
/*
- * If we're about to sleep, ignore incoming browse packets.
+ * Search for printers...
*/
- if (Sleeping)
- return;
+ cupsdLogMessage(CUPSD_LOG_DEBUG2, "UpdateLDAPBrowse: %s", ServerName);
- /*
- * Figure out where it came from...
- */
+ BrowseLDAPRefresh = time(NULL) + BrowseInterval;
-#ifdef AF_INET6
- if (srcaddr.addr.sa_family == AF_INET6)
- {
- address[0] = ntohl(srcaddr.ipv6.sin6_addr.s6_addr32[0]);
- address[1] = ntohl(srcaddr.ipv6.sin6_addr.s6_addr32[1]);
- address[2] = ntohl(srcaddr.ipv6.sin6_addr.s6_addr32[2]);
- address[3] = ntohl(srcaddr.ipv6.sin6_addr.s6_addr32[3]);
- }
- else
-#endif /* AF_INET6 */
+ rc = ldap_search_s(BrowseLDAPHandle, BrowseLDAPDN, LDAP_SCOPE_SUBTREE,
+ "(objectclass=cupsPrinter)", (char **)ldap_attrs, 0, &res);
+ if (rc != LDAP_SUCCESS)
{
- address[0] = 0;
- address[1] = 0;
- address[2] = 0;
- address[3] = ntohl(srcaddr.ipv4.sin_addr.s_addr);
+ cupsdLogMessage(CUPSD_LOG_ERROR,
+ "LDAP search returned error %d: %s", rc,
+ ldap_err2string(rc));
+ return;
}
- if (HostNameLookups)
- httpAddrLookup(&srcaddr, srcname, sizeof(srcname));
- else
- httpAddrString(&srcaddr, srcname, sizeof(srcname));
-
- len = strlen(srcname);
+ limit = ldap_count_entries(BrowseLDAPHandle, res);
+ cupsdLogMessage(CUPSD_LOG_DEBUG2, "LDAP search returned %d entries", limit);
+ if (limit < 1)
+ return;
/*
- * Do ACL stuff...
+ * Loop through the available printers...
*/
- if (BrowseACL)
+ for (e = ldap_first_entry(BrowseLDAPHandle, res);
+ e;
+ e = ldap_next_entry(BrowseLDAPHandle, e))
{
- if (httpAddrLocalhost(&srcaddr) || !strcasecmp(srcname, "localhost"))
- {
- /*
- * Access from localhost (127.0.0.1) is always allowed...
- */
+ /*
+ * Get the required values from this entry...
+ */
- auth = AUTH_ALLOW;
- }
- else
- {
- /*
- * Do authorization checks on the domain/address...
- */
+ if ((value = ldap_get_values(BrowseLDAPHandle, e,
+ "printerDescription")) == NULL)
+ continue;
- switch (BrowseACL->order_type)
- {
- default :
- auth = AUTH_DENY; /* anti-compiler-warning-code */
- break;
+ strlcpy(info, *value, sizeof(info));
+ ldap_value_free(value);
- case AUTH_ALLOW : /* Order Deny,Allow */
- auth = AUTH_ALLOW;
+ if ((value = ldap_get_values(BrowseLDAPHandle, e,
+ "printerLocation")) == NULL)
+ continue;
- if (cupsdCheckAuth(address, srcname, len,
- BrowseACL->num_deny, BrowseACL->deny))
- auth = AUTH_DENY;
+ strlcpy(location, *value, sizeof(location));
+ ldap_value_free(value);
- if (cupsdCheckAuth(address, srcname, len,
- BrowseACL->num_allow, BrowseACL->allow))
- auth = AUTH_ALLOW;
- break;
+ if ((value = ldap_get_values(BrowseLDAPHandle, e,
+ "printerMakeAndModel")) == NULL)
+ continue;
- case AUTH_DENY : /* Order Allow,Deny */
- auth = AUTH_DENY;
+ strlcpy(make_model, *value, sizeof(make_model));
+ ldap_value_free(value);
- if (cupsdCheckAuth(address, srcname, len,
- BrowseACL->num_allow, BrowseACL->allow))
- auth = AUTH_ALLOW;
+ if ((value = ldap_get_values(BrowseLDAPHandle, e,
+ "printerType")) == NULL)
+ continue;
- if (cupsdCheckAuth(address, srcname, len,
- BrowseACL->num_deny, BrowseACL->deny))
- auth = AUTH_DENY;
- break;
- }
- }
- }
- else
- auth = AUTH_ALLOW;
+ type = atoi(*value);
+ ldap_value_free(value);
- if (auth == AUTH_DENY)
- {
- cupsdLogMessage(CUPSD_LOG_DEBUG,
- "cupsdUpdateCUPSBrowse: Refused %d bytes from %s", bytes,
- srcname);
- return;
- }
+ if ((value = ldap_get_values(BrowseLDAPHandle, e,
+ "printerURI")) == NULL)
+ continue;
- cupsdLogMessage(CUPSD_LOG_DEBUG2,
- "cupsdUpdateCUPSBrowse: (%d bytes from %s) %s", bytes,
- srcname, packet);
+ strlcpy(uri, *value, sizeof(uri));
+ ldap_value_free(value);
- /*
- * Parse packet...
- */
+ /*
+ * Process the entry as browse data...
+ */
+
+ if (!is_local_queue(uri, host, sizeof(host), resource, sizeof(resource)))
+ process_browse_data(uri, host, resource, type, IPP_PRINTER_IDLE,
+ location, info, make_model, 0, NULL);
- if (sscanf(packet, "%x%x%1023s", &type, &state, uri) < 3)
- {
- cupsdLogMessage(CUPSD_LOG_WARN,
- "cupsdUpdateCUPSBrowse: Garbled browse packet - %s", packet);
- return;
}
+}
+#endif /* HAVE_OPENLDAP */
- strcpy(location, "Location Unknown");
- strcpy(info, "No Information Available");
- make_model[0] = '\0';
- num_attrs = 0;
- attrs = NULL;
- if ((pptr = strchr(packet, '\"')) != NULL)
- {
- /*
- * Have extended information; can't use sscanf for it because not all
- * sscanf's allow empty strings with %[^\"]...
- */
+#ifdef HAVE_LIBSLP
+/*
+ * 'cupsdUpdateSLPBrowse()' - Get browsing information via SLP.
+ */
- for (i = 0, pptr ++;
- i < (sizeof(location) - 1) && *pptr && *pptr != '\"';
- i ++, pptr ++)
- location[i] = *pptr;
+void
+cupsdUpdateSLPBrowse(void)
+{
+ slpsrvurl_t *s, /* Temporary list of service URLs */
+ *next; /* Next service in list */
+ cupsd_printer_t p; /* Printer information */
+ const char *uri; /* Pointer to printer URI */
+ char host[HTTP_MAX_URI], /* Host portion of URI */
+ resource[HTTP_MAX_URI]; /* Resource portion of URI */
- if (i)
- location[i] = '\0';
- if (*pptr == '\"')
- pptr ++;
+ /*
+ * Reset the refresh time...
+ */
- while (*pptr && isspace(*pptr & 255))
- pptr ++;
+ BrowseSLPRefresh = time(NULL) + BrowseInterval;
- if (*pptr == '\"')
- {
- for (i = 0, pptr ++;
- i < (sizeof(info) - 1) && *pptr && *pptr != '\"';
- i ++, pptr ++)
- info[i] = *pptr;
+ /*
+ * Poll for remote printers using SLP...
+ */
- info[i] = '\0';
+ s = NULL;
- if (*pptr == '\"')
- pptr ++;
+ SLPFindSrvs(BrowseSLPHandle, SLP_CUPS_SRVTYPE, "", "",
+ slp_url_callback, &s);
- while (*pptr && isspace(*pptr & 255))
- pptr ++;
+ /*
+ * Loop through the list of available printers...
+ */
- if (*pptr == '\"')
- {
- for (i = 0, pptr ++;
- i < (sizeof(make_model) - 1) && *pptr && *pptr != '\"';
- i ++, pptr ++)
- make_model[i] = *pptr;
+ for (; s; s = next)
+ {
+ /*
+ * Save the "next" pointer...
+ */
- if (*pptr == '\"')
- pptr ++;
+ next = s->next;
- make_model[i] = '\0';
+ /*
+ * Load a cupsd_printer_t structure with the SLP service attributes...
+ */
- if (*pptr)
- num_attrs = cupsParseOptions(pptr, num_attrs, &attrs);
- }
- }
- }
+ SLPFindAttrs(BrowseSLPHandle, s->url, "", "", slp_attr_callback, &p);
- DEBUG_puts(packet);
- DEBUG_printf(("type=%x, state=%x, uri=\"%s\"\n"
- "location=\"%s\", info=\"%s\", make_model=\"%s\"\n",
- type, state, uri, location, info, make_model));
+ /*
+ * Process this printer entry...
+ */
- /*
- * Pull the URI apart to see if this is a local or remote printer...
- */
+ uri = s->url + SLP_CUPS_SRVLEN + 1;
- if (is_local_queue(uri, host, sizeof(host), resource, sizeof(resource)))
- {
- cupsFreeOptions(num_attrs, attrs);
- return;
- }
+ if (!strncmp(uri, "http://", 7) || !strncmp(uri, "ipp://", 6))
+ {
+ /*
+ * Pull the URI apart to see if this is a local or remote printer...
+ */
- /*
- * Do relaying...
- */
+ if (!is_local_queue(uri, host, sizeof(host), resource, sizeof(resource)))
+ process_browse_data(uri, host, resource, p.type, IPP_PRINTER_IDLE,
+ p.location, p.info, p.make_model, 0, NULL);
+ }
- for (i = 0; i < NumRelays; i ++)
- if (cupsdCheckAuth(address, srcname, len, 1, &(Relays[i].from)))
- if (sendto(BrowseSocket, packet, bytes, 0,
- (struct sockaddr *)&(Relays[i].to),
- httpAddrLength(&(Relays[i].to))) <= 0)
- {
- cupsdLogMessage(CUPSD_LOG_ERROR,
- "cupsdUpdateCUPSBrowse: sendto failed for relay %d - %s.",
- i + 1, strerror(errno));
- cupsFreeOptions(num_attrs, attrs);
- return;
- }
+ /*
+ * Free this listing...
+ */
- /*
- * Process the browse data...
- */
+ cupsdClearString(&p.info);
+ cupsdClearString(&p.location);
+ cupsdClearString(&p.make_model);
- process_browse_data(uri, host, resource, (cups_ptype_t)type,
- (ipp_pstate_t)state, location, info, make_model,
- num_attrs, attrs);
+ free(s);
+ }
}
+#endif /* HAVE_LIBSLP */
-#ifdef HAVE_DNSSD
/*
- * 'cupsdUpdateDNSSDBrowse()' - Handle DNS-SD queries.
+ * 'dequote()' - Remote quotes from a string.
*/
-void
-cupsdUpdateDNSSDBrowse(
- cupsd_printer_t *p) /* I - Printer being queried */
+static char * /* O - Dequoted string */
+dequote(char *d, /* I - Destination string */
+ const char *s, /* I - Source string */
+ int dlen) /* I - Destination length */
{
- DNSServiceErrorType sdErr; /* Service discovery error */
+ char *dptr; /* Pointer into destination */
- if ((sdErr = DNSServiceProcessResult(p->dnssd_ipp_ref))
- != kDNSServiceErr_NoError)
+ if (s)
{
- cupsdLogMessage(CUPSD_LOG_ERROR,
- "DNS Service Discovery registration error %d for \"%s\"!",
- sdErr, p->name);
- cupsdRemoveSelect(p->dnssd_ipp_fd);
- DNSServiceRefDeallocate(p->dnssd_ipp_ref);
+ for (dptr = d, dlen --; *s && dlen > 0; s ++)
+ if (*s != '\"')
+ {
+ *dptr++ = *s;
+ dlen --;
+ }
- p->dnssd_ipp_ref = NULL;
- p->dnssd_ipp_fd = -1;
+ *dptr = '\0';
}
+ else
+ *d = '\0';
+
+ return (d);
}
-#endif /* HAVE_DNSSD */
-#ifdef HAVE_OPENLDAP
/*
- * 'cupsdUpdateLDAPBrowse()' - Scan for new printers via LDAP...
+ * 'is_local_queue()' - Determine whether the URI points at a local queue.
*/
-void
-cupsdUpdateLDAPBrowse(void)
+static int /* O - 1 = local, 0 = remote, -1 = bad URI */
+is_local_queue(const char *uri, /* I - Printer URI */
+ char *host, /* O - Host string */
+ int hostlen, /* I - Length of host buffer */
+ char *resource, /* O - Resource string */
+ int resourcelen) /* I - Length of resource buffer */
{
- char uri[HTTP_MAX_URI], /* Printer URI */
- host[HTTP_MAX_URI], /* Hostname */
- resource[HTTP_MAX_URI], /* Resource path */
- location[1024], /* Printer location */
- info[1024], /* Printer information */
- make_model[1024], /* Printer make and model */
- **value; /* Holds the returned data from LDAP */
- int type; /* Printer type */
- int rc; /* LDAP status */
- int limit; /* Size limit */
- LDAPMessage *res, /* LDAP search results */
- *e; /* Current entry from search */
+ char scheme[32], /* Scheme portion of URI */
+ username[HTTP_MAX_URI]; /* Username portion of URI */
+ int port; /* Port portion of URI */
+ cupsd_netif_t *iface; /* Network interface */
/*
- * Search for printers...
+ * Pull the URI apart to see if this is a local or remote printer...
*/
- cupsdLogMessage(CUPSD_LOG_DEBUG2, "UpdateLDAPBrowse: %s", ServerName);
-
- BrowseLDAPRefresh = time(NULL) + BrowseInterval;
-
- rc = ldap_search_s(BrowseLDAPHandle, BrowseLDAPDN, LDAP_SCOPE_SUBTREE,
- "(objectclass=cupsPrinter)", (char **)ldap_attrs, 0, &res);
- if (rc != LDAP_SUCCESS)
- {
- cupsdLogMessage(CUPSD_LOG_ERROR,
- "LDAP search returned error %d: %s", rc,
- ldap_err2string(rc));
- return;
- }
+ if (httpSeparateURI(HTTP_URI_CODING_ALL, uri, scheme, sizeof(scheme),
+ username, sizeof(username), host, hostlen, &port,
+ resource, resourcelen) < HTTP_URI_OK)
+ return (-1);
- limit = ldap_count_entries(BrowseLDAPHandle, res);
- cupsdLogMessage(CUPSD_LOG_DEBUG2, "LDAP search returned %d entries", limit);
- if (limit < 1)
- return;
+ DEBUG_printf(("host=\"%s\", ServerName=\"%s\"\n", host, ServerName));
/*
- * Loop through the available printers...
+ * Check for local server addresses...
*/
- for (e = ldap_first_entry(BrowseLDAPHandle, res);
- e;
- e = ldap_next_entry(BrowseLDAPHandle, e))
- {
- /*
- * Get the required values from this entry...
- */
-
- if ((value = ldap_get_values(BrowseLDAPHandle, e,
- "printerDescription")) == NULL)
- continue;
-
- strlcpy(info, *value, sizeof(info));
- ldap_value_free(value);
-
- if ((value = ldap_get_values(BrowseLDAPHandle, e,
- "printerLocation")) == NULL)
- continue;
-
- strlcpy(location, *value, sizeof(location));
- ldap_value_free(value);
-
- if ((value = ldap_get_values(BrowseLDAPHandle, e,
- "printerMakeAndModel")) == NULL)
- continue;
-
- strlcpy(make_model, *value, sizeof(make_model));
- ldap_value_free(value);
-
- if ((value = ldap_get_values(BrowseLDAPHandle, e,
- "printerType")) == NULL)
- continue;
-
- type = atoi(*value);
- ldap_value_free(value);
-
- if ((value = ldap_get_values(BrowseLDAPHandle, e,
- "printerURI")) == NULL)
- continue;
+ if (!strcasecmp(host, ServerName) && port == LocalPort)
+ return (1);
- strlcpy(uri, *value, sizeof(uri));
- ldap_value_free(value);
+ cupsdNetIFUpdate();
- /*
- * Process the entry as browse data...
- */
+ for (iface = (cupsd_netif_t *)cupsArrayFirst(NetIFList);
+ iface;
+ iface = (cupsd_netif_t *)cupsArrayNext(NetIFList))
+ if (!strcasecmp(host, iface->hostname) && port == iface->port)
+ return (1);
- if (!is_local_queue(uri, host, sizeof(host), resource, sizeof(resource)))
- process_browse_data(uri, host, resource, type, IPP_PRINTER_IDLE,
- location, info, make_model, 0, NULL);
+ /*
+ * If we get here, the printer is remote...
+ */
- }
+ return (0);
}
-#endif /* HAVE_OPENLDAP */
/*
- * 'cupsdUpdatePolling()' - Read status messages from the poll daemons.
- */
-
-void
-cupsdUpdatePolling(void)
-{
- char *ptr, /* Pointer to end of line in buffer */
- message[1024]; /* Pointer to message text */
- int loglevel; /* Log level for message */
-
-
- while ((ptr = cupsdStatBufUpdate(PollStatusBuffer, &loglevel,
- message, sizeof(message))) != NULL)
- if (!strchr(PollStatusBuffer->buffer, '\n'))
- break;
-
- if (ptr == NULL && !PollStatusBuffer->bufused)
- {
- /*
- * All polling processes have died; stop polling...
- */
-
- cupsdLogMessage(CUPSD_LOG_ERROR,
- "cupsdUpdatePolling: all polling processes have exited!");
- cupsdStopPolling();
- }
-}
-
-
-#ifdef HAVE_LIBSLP
-/*
- * 'cupsdUpdateSLPBrowse()' - Get browsing information via SLP.
- */
-
-void
-cupsdUpdateSLPBrowse(void)
-{
- slpsrvurl_t *s, /* Temporary list of service URLs */
- *next; /* Next service in list */
- cupsd_printer_t p; /* Printer information */
- const char *uri; /* Pointer to printer URI */
- char host[HTTP_MAX_URI], /* Host portion of URI */
- resource[HTTP_MAX_URI]; /* Resource portion of URI */
-
-
- /*
- * Reset the refresh time...
- */
-
- BrowseSLPRefresh = time(NULL) + BrowseInterval;
-
- /*
- * Poll for remote printers using SLP...
- */
-
- s = NULL;
-
- SLPFindSrvs(BrowseSLPHandle, SLP_CUPS_SRVTYPE, "", "",
- slp_url_callback, &s);
-
- /*
- * Loop through the list of available printers...
- */
-
- for (; s; s = next)
- {
- /*
- * Save the "next" pointer...
- */
-
- next = s->next;
-
- /*
- * Load a cupsd_printer_t structure with the SLP service attributes...
- */
-
- SLPFindAttrs(BrowseSLPHandle, s->url, "", "", slp_attr_callback, &p);
-
- /*
- * Process this printer entry...
- */
-
- uri = s->url + SLP_CUPS_SRVLEN + 1;
-
- if (!strncmp(uri, "http://", 7) || !strncmp(uri, "ipp://", 6))
- {
- /*
- * Pull the URI apart to see if this is a local or remote printer...
- */
-
- if (!is_local_queue(uri, host, sizeof(host), resource, sizeof(resource)))
- process_browse_data(uri, host, resource, p.type, IPP_PRINTER_IDLE,
- p.location, p.info, p.make_model, 0, NULL);
- }
-
- /*
- * Free this listing...
- */
-
- cupsdClearString(&p.info);
- cupsdClearString(&p.location);
- cupsdClearString(&p.make_model);
-
- free(s);
- }
-}
-#endif /* HAVE_LIBSLP */
-
-
-/*
- * 'dequote()' - Remote quotes from a string.
- */
-
-static char * /* O - Dequoted string */
-dequote(char *d, /* I - Destination string */
- const char *s, /* I - Source string */
- int dlen) /* I - Destination length */
-{
- char *dptr; /* Pointer into destination */
-
-
- if (s)
- {
- for (dptr = d, dlen --; *s && dlen > 0; s ++)
- if (*s != '\"')
- {
- *dptr++ = *s;
- dlen --;
- }
-
- *dptr = '\0';
- }
- else
- *d = '\0';
-
- return (d);
-}
-
-
-/*
- * 'is_local_queue()' - Determine whether the URI points at a local queue.
- */
-
-static int /* O - 1 = local, 0 = remote, -1 = bad URI */
-is_local_queue(const char *uri, /* I - Printer URI */
- char *host, /* O - Host string */
- int hostlen, /* I - Length of host buffer */
- char *resource, /* O - Resource string */
- int resourcelen) /* I - Length of resource buffer */
-{
- char scheme[32], /* Scheme portion of URI */
- username[HTTP_MAX_URI]; /* Username portion of URI */
- int port; /* Port portion of URI */
- cupsd_netif_t *iface; /* Network interface */
-
-
- /*
- * Pull the URI apart to see if this is a local or remote printer...
- */
-
- if (httpSeparateURI(HTTP_URI_CODING_ALL, uri, scheme, sizeof(scheme),
- username, sizeof(username), host, hostlen, &port,
- resource, resourcelen) < HTTP_URI_OK)
- return (-1);
-
- DEBUG_printf(("host=\"%s\", ServerName=\"%s\"\n", host, ServerName));
-
- /*
- * Check for local server addresses...
- */
-
- if (!strcasecmp(host, ServerName) && port == LocalPort)
- return (1);
-
- cupsdNetIFUpdate();
-
- for (iface = (cupsd_netif_t *)cupsArrayFirst(NetIFList);
- iface;
- iface = (cupsd_netif_t *)cupsArrayNext(NetIFList))
- if (!strcasecmp(host, iface->hostname) && port == iface->port)
- return (1);
-
- /*
- * If we get here, the printer is remote...
- */
-
- return (0);
-}
-
-
-/*
- * 'process_browse_data()' - Process new browse data.
+ * 'process_browse_data()' - Process new browse data.
*/
static void
/*
- * End of "$Id: dirsvc.c 6354 2007-03-19 06:16:32Z mike $".
+ * 'update_cups_browse()' - Update the browse lists using the CUPS protocol.
+ */
+
+static void
+update_cups_browse(void)
+{
+ int i; /* Looping var */
+ int auth; /* Authorization status */
+ int len; /* Length of name string */
+ int bytes; /* Number of bytes left */
+ char packet[1541], /* Broadcast packet */
+ *pptr; /* Pointer into packet */
+ socklen_t srclen; /* Length of source address */
+ http_addr_t srcaddr; /* Source address */
+ char srcname[1024]; /* Source hostname */
+ unsigned address[4]; /* Source address */
+ unsigned type; /* Printer type */
+ unsigned state; /* Printer state */
+ char uri[HTTP_MAX_URI], /* Printer URI */
+ host[HTTP_MAX_URI], /* Host portion of URI */
+ resource[HTTP_MAX_URI], /* Resource portion of URI */
+ info[IPP_MAX_NAME], /* Information string */
+ location[IPP_MAX_NAME], /* Location string */
+ make_model[IPP_MAX_NAME];/* Make and model string */
+ int num_attrs; /* Number of attributes */
+ cups_option_t *attrs; /* Attributes */
+
+
+ /*
+ * Read a packet from the browse socket...
+ */
+
+ srclen = sizeof(srcaddr);
+ if ((bytes = recvfrom(BrowseSocket, packet, sizeof(packet) - 1, 0,
+ (struct sockaddr *)&srcaddr, &srclen)) < 0)
+ {
+ /*
+ * "Connection refused" is returned under Linux if the destination port
+ * or address is unreachable from a previous sendto(); check for the
+ * error here and ignore it for now...
+ */
+
+ if (errno != ECONNREFUSED && errno != EAGAIN)
+ {
+ cupsdLogMessage(CUPSD_LOG_ERROR, "Browse recv failed - %s.",
+ strerror(errno));
+ cupsdLogMessage(CUPSD_LOG_ERROR, "Browsing turned off.");
+
+ cupsdStopBrowsing();
+ Browsing = 0;
+ }
+
+ return;
+ }
+
+ packet[bytes] = '\0';
+
+ /*
+ * If we're about to sleep, ignore incoming browse packets.
+ */
+
+ if (Sleeping)
+ return;
+
+ /*
+ * Figure out where it came from...
+ */
+
+#ifdef AF_INET6
+ if (srcaddr.addr.sa_family == AF_INET6)
+ {
+ address[0] = ntohl(srcaddr.ipv6.sin6_addr.s6_addr32[0]);
+ address[1] = ntohl(srcaddr.ipv6.sin6_addr.s6_addr32[1]);
+ address[2] = ntohl(srcaddr.ipv6.sin6_addr.s6_addr32[2]);
+ address[3] = ntohl(srcaddr.ipv6.sin6_addr.s6_addr32[3]);
+ }
+ else
+#endif /* AF_INET6 */
+ {
+ address[0] = 0;
+ address[1] = 0;
+ address[2] = 0;
+ address[3] = ntohl(srcaddr.ipv4.sin_addr.s_addr);
+ }
+
+ if (HostNameLookups)
+ httpAddrLookup(&srcaddr, srcname, sizeof(srcname));
+ else
+ httpAddrString(&srcaddr, srcname, sizeof(srcname));
+
+ len = strlen(srcname);
+
+ /*
+ * Do ACL stuff...
+ */
+
+ if (BrowseACL)
+ {
+ if (httpAddrLocalhost(&srcaddr) || !strcasecmp(srcname, "localhost"))
+ {
+ /*
+ * Access from localhost (127.0.0.1) is always allowed...
+ */
+
+ auth = AUTH_ALLOW;
+ }
+ else
+ {
+ /*
+ * Do authorization checks on the domain/address...
+ */
+
+ switch (BrowseACL->order_type)
+ {
+ default :
+ auth = AUTH_DENY; /* anti-compiler-warning-code */
+ break;
+
+ case AUTH_ALLOW : /* Order Deny,Allow */
+ auth = AUTH_ALLOW;
+
+ if (cupsdCheckAuth(address, srcname, len,
+ BrowseACL->num_deny, BrowseACL->deny))
+ auth = AUTH_DENY;
+
+ if (cupsdCheckAuth(address, srcname, len,
+ BrowseACL->num_allow, BrowseACL->allow))
+ auth = AUTH_ALLOW;
+ break;
+
+ case AUTH_DENY : /* Order Allow,Deny */
+ auth = AUTH_DENY;
+
+ if (cupsdCheckAuth(address, srcname, len,
+ BrowseACL->num_allow, BrowseACL->allow))
+ auth = AUTH_ALLOW;
+
+ if (cupsdCheckAuth(address, srcname, len,
+ BrowseACL->num_deny, BrowseACL->deny))
+ auth = AUTH_DENY;
+ break;
+ }
+ }
+ }
+ else
+ auth = AUTH_ALLOW;
+
+ if (auth == AUTH_DENY)
+ {
+ cupsdLogMessage(CUPSD_LOG_DEBUG,
+ "update_cups_browse: Refused %d bytes from %s", bytes,
+ srcname);
+ return;
+ }
+
+ cupsdLogMessage(CUPSD_LOG_DEBUG2,
+ "update_cups_browse: (%d bytes from %s) %s", bytes,
+ srcname, packet);
+
+ /*
+ * Parse packet...
+ */
+
+ if (sscanf(packet, "%x%x%1023s", &type, &state, uri) < 3)
+ {
+ cupsdLogMessage(CUPSD_LOG_WARN,
+ "update_cups_browse: Garbled browse packet - %s", packet);
+ return;
+ }
+
+ strcpy(location, "Location Unknown");
+ strcpy(info, "No Information Available");
+ make_model[0] = '\0';
+ num_attrs = 0;
+ attrs = NULL;
+
+ if ((pptr = strchr(packet, '\"')) != NULL)
+ {
+ /*
+ * Have extended information; can't use sscanf for it because not all
+ * sscanf's allow empty strings with %[^\"]...
+ */
+
+ for (i = 0, pptr ++;
+ i < (sizeof(location) - 1) && *pptr && *pptr != '\"';
+ i ++, pptr ++)
+ location[i] = *pptr;
+
+ if (i)
+ location[i] = '\0';
+
+ if (*pptr == '\"')
+ pptr ++;
+
+ while (*pptr && isspace(*pptr & 255))
+ pptr ++;
+
+ if (*pptr == '\"')
+ {
+ for (i = 0, pptr ++;
+ i < (sizeof(info) - 1) && *pptr && *pptr != '\"';
+ i ++, pptr ++)
+ info[i] = *pptr;
+
+ info[i] = '\0';
+
+ if (*pptr == '\"')
+ pptr ++;
+
+ while (*pptr && isspace(*pptr & 255))
+ pptr ++;
+
+ if (*pptr == '\"')
+ {
+ for (i = 0, pptr ++;
+ i < (sizeof(make_model) - 1) && *pptr && *pptr != '\"';
+ i ++, pptr ++)
+ make_model[i] = *pptr;
+
+ if (*pptr == '\"')
+ pptr ++;
+
+ make_model[i] = '\0';
+
+ if (*pptr)
+ num_attrs = cupsParseOptions(pptr, num_attrs, &attrs);
+ }
+ }
+ }
+
+ DEBUG_puts(packet);
+ DEBUG_printf(("type=%x, state=%x, uri=\"%s\"\n"
+ "location=\"%s\", info=\"%s\", make_model=\"%s\"\n",
+ type, state, uri, location, info, make_model));
+
+ /*
+ * Pull the URI apart to see if this is a local or remote printer...
+ */
+
+ if (is_local_queue(uri, host, sizeof(host), resource, sizeof(resource)))
+ {
+ cupsFreeOptions(num_attrs, attrs);
+ return;
+ }
+
+ /*
+ * Do relaying...
+ */
+
+ for (i = 0; i < NumRelays; i ++)
+ if (cupsdCheckAuth(address, srcname, len, 1, &(Relays[i].from)))
+ if (sendto(BrowseSocket, packet, bytes, 0,
+ (struct sockaddr *)&(Relays[i].to),
+ httpAddrLength(&(Relays[i].to))) <= 0)
+ {
+ cupsdLogMessage(CUPSD_LOG_ERROR,
+ "update_cups_browse: sendto failed for relay %d - %s.",
+ i + 1, strerror(errno));
+ cupsFreeOptions(num_attrs, attrs);
+ return;
+ }
+
+ /*
+ * Process the browse data...
+ */
+
+ process_browse_data(uri, host, resource, (cups_ptype_t)type,
+ (ipp_pstate_t)state, location, info, make_model,
+ num_attrs, attrs);
+}
+
+
+/*
+ * 'update_polling()' - Read status messages from the poll daemons.
+ */
+
+static void
+update_polling(void)
+{
+ char *ptr, /* Pointer to end of line in buffer */
+ message[1024]; /* Pointer to message text */
+ int loglevel; /* Log level for message */
+
+
+ while ((ptr = cupsdStatBufUpdate(PollStatusBuffer, &loglevel,
+ message, sizeof(message))) != NULL)
+ if (!strchr(PollStatusBuffer->buffer, '\n'))
+ break;
+
+ if (ptr == NULL && !PollStatusBuffer->bufused)
+ {
+ /*
+ * All polling processes have died; stop polling...
+ */
+
+ cupsdLogMessage(CUPSD_LOG_ERROR,
+ "update_polling: all polling processes have exited!");
+ cupsdStopPolling();
+ }
+}
+
+
+/*
+ * End of "$Id: dirsvc.c 6376 2007-03-21 06:39:10Z mike $".
*/
/*
- * "$Id: dirsvc.h 6291 2007-02-19 21:54:27Z mike $"
+ * "$Id: dirsvc.h 6376 2007-03-21 06:39:10Z mike $"
*
* Directory services definitions for the Common UNIX Printing System
* (CUPS) scheduler.
extern void cupsdStartPolling(void);
extern void cupsdStopBrowsing(void);
extern void cupsdStopPolling(void);
-extern void cupsdUpdateCUPSBrowse(void);
#ifdef HAVE_DNSSD
extern void cupsdUpdateDNSSDBrowse(cupsd_printer_t *p);
#endif /* HAVE_DNSSD */
#ifdef HAVE_LDAP
extern void cupsdUpdateLDAPBrowse(void);
#endif /* HAVE_LDAP */
-extern void cupsdUpdatePolling(void);
extern void cupsdUpdateSLPBrowse(void);
/*
- * End of "$Id: dirsvc.h 6291 2007-02-19 21:54:27Z mike $".
+ * End of "$Id: dirsvc.h 6376 2007-03-21 06:39:10Z mike $".
*/
/*
- * "$Id: ipp.c 6370 2007-03-20 14:36:12Z mike $"
+ * "$Id: ipp.c 6383 2007-03-21 20:01:20Z mike $"
*
* IPP routines for the Common UNIX Printing System (CUPS) scheduler.
*
# include <paper.h>
#endif /* HAVE_LIBPAPER */
-#ifdef HAVE_MEMBERSHIP_H
-# include <membership.h>
-#endif /* HAVE_MEMBERSHIP_H */
-#ifdef HAVE_MEMBERSHIPPRIV_H
-# include <membershipPriv.h>
-#else
+#ifdef __APPLE__
+# ifdef HAVE_MEMBERSHIP_H
+# include <membership.h>
+# endif /* HAVE_MEMBERSHIP_H */
+# ifdef HAVE_MEMBERSHIPPRIV_H
+# include <membershipPriv.h>
+# else
extern int mbr_user_name_to_uuid(const char* name, uuid_t uu);
extern int mbr_group_name_to_uuid(const char* name, uuid_t uu);
extern int mbr_check_membership_by_id(uuid_t user, gid_t group, int* ismember);
-#endif /* HAVE_MEMBERSHIPPRIV_H */
+# endif /* HAVE_MEMBERSHIPPRIV_H */
+#endif /* __APPLE__ */
/*
static void save_krb5_creds(cupsd_client_t *con, cupsd_job_t *job);
#endif /* HAVE_GSSAPI && HAVE_KRB5_H */
static void send_document(cupsd_client_t *con, ipp_attribute_t *uri);
-static void send_http_error(cupsd_client_t *con, http_status_t status);
+static void send_http_error(cupsd_client_t *con, http_status_t status,
+ cupsd_printer_t *printer);
static void send_ipp_status(cupsd_client_t *con, ipp_status_t status,
const char *message, ...)
# ifdef __GNUC__
con->http.fd, con->response->request.status.status_code,
ippErrorString(con->response->request.status.status_code));
- if (cupsdSendHeader(con, HTTP_OK, "application/ipp"))
+ if (cupsdSendHeader(con, HTTP_OK, "application/ipp", AUTH_NONE))
{
#ifdef CUPSD_USE_CHUNKING
/*
if ((status = cupsdCheckPolicy(printer->op_policy_ptr, con, NULL)) != HTTP_OK)
{
- send_http_error(con, status);
+ send_http_error(con, status, printer);
return;
}
if ((status = cupsdCheckPolicy(DefaultPolicyPtr, con, NULL)) != HTTP_OK)
{
- send_http_error(con, status);
+ send_http_error(con, status, NULL);
return;
}
* Check policy...
*/
- auth_info = ippFindAttribute(job->attrs, "auth-info", IPP_TAG_TEXT);
+ auth_info = ippFindAttribute(con->request, "auth-info", IPP_TAG_TEXT);
if ((status = cupsdCheckPolicy(printer->op_policy_ptr, con, NULL)) != HTTP_OK)
{
- send_http_error(con, status);
+ send_http_error(con, status, printer);
return (NULL);
}
else if ((printer->type & CUPS_PRINTER_AUTHENTICATED) &&
!con->username[0] && !auth_info)
{
- send_http_error(con, HTTP_UNAUTHORIZED);
+ send_http_error(con, HTTP_UNAUTHORIZED, printer);
return (NULL);
}
#ifdef HAVE_SSL
* Require encryption of auth-info over non-local connections...
*/
- send_http_error(con, HTTP_UPGRADE_REQUIRED);
+ send_http_error(con, HTTP_UPGRADE_REQUIRED, printer);
return (NULL);
}
#endif /* HAVE_SSL */
while (attr && attr->group_tag != IPP_TAG_ZERO)
{
- if (!strcmp(attr->name, "notify-recipient") &&
+ if (!strcmp(attr->name, "notify-recipient-uri") &&
attr->value_tag == IPP_TAG_URI)
recipient = attr->values[0].string.text;
else if (!strcmp(attr->name, "notify-pull-method") &&
if ((status = cupsdCheckPolicy(DefaultPolicyPtr, con, NULL)) != HTTP_OK)
{
- send_http_error(con, status);
+ send_http_error(con, status, NULL);
return;
}
if (!validate_user(job, con, job->username, username, sizeof(username)))
{
- send_http_error(con, HTTP_UNAUTHORIZED);
+ send_http_error(con, HTTP_UNAUTHORIZED, NULL);
return;
}
if ((status = cupsdCheckPolicy(DefaultPolicyPtr, con, NULL)) != HTTP_OK)
{
- send_http_error(con, status);
+ send_http_error(con, status, NULL);
return;
}
if ((status = cupsdCheckPolicy(printer->op_policy_ptr, con,
NULL)) != HTTP_OK)
{
- send_http_error(con, status);
+ send_http_error(con, status, printer);
return;
}
if (!validate_user(job, con, job->username, username, sizeof(username)))
{
- send_http_error(con, HTTP_UNAUTHORIZED);
+ send_http_error(con, HTTP_UNAUTHORIZED, NULL);
return;
}
DefaultPolicyPtr,
con, sub->owner)) != HTTP_OK)
{
- send_http_error(con, status);
+ send_http_error(con, status, sub->dest);
return;
}
if ((status = cupsdCheckPolicy(printer->op_policy_ptr, con,
NULL)) != HTTP_OK)
{
- send_http_error(con, status);
+ send_http_error(con, status, printer);
return;
}
}
else if ((status = cupsdCheckPolicy(DefaultPolicyPtr, con, NULL)) != HTTP_OK)
{
- send_http_error(con, status);
+ send_http_error(con, status, NULL);
return;
}
if ((status = cupsdCheckPolicy(DefaultPolicyPtr, con, NULL)) != HTTP_OK)
{
- send_http_error(con, status);
+ send_http_error(con, status, NULL);
return;
}
if ((status = cupsdCheckPolicy(DefaultPolicyPtr, con, NULL)) != HTTP_OK)
{
- send_http_error(con, status);
+ send_http_error(con, status, NULL);
return;
}
if ((status = cupsdCheckPolicy(DefaultPolicyPtr, con, NULL)) != HTTP_OK)
{
- send_http_error(con, status);
+ send_http_error(con, status, NULL);
return;
}
if ((status = cupsdCheckPolicy(DefaultPolicyPtr, con, NULL)) != HTTP_OK)
{
- send_http_error(con, status);
+ send_http_error(con, status, NULL);
return;
}
if ((status = cupsdCheckPolicy(printer->op_policy_ptr, con,
NULL)) != HTTP_OK)
{
- send_http_error(con, status);
+ send_http_error(con, status, printer);
return;
}
}
else if ((status = cupsdCheckPolicy(DefaultPolicyPtr, con, NULL)) != HTTP_OK)
{
- send_http_error(con, status);
+ send_http_error(con, status, NULL);
return;
}
DefaultPolicyPtr,
con, sub->owner)) != HTTP_OK)
{
- send_http_error(con, status);
+ send_http_error(con, status, sub->dest);
return;
}
if ((status = cupsdCheckPolicy(DefaultPolicyPtr, con, NULL)) != HTTP_OK)
{
- send_http_error(con, status);
+ send_http_error(con, status, NULL);
return;
}
if ((status = cupsdCheckPolicy(printer->op_policy_ptr, con, NULL)) != HTTP_OK)
{
- send_http_error(con, status);
+ send_http_error(con, status, printer);
return;
}
if ((status = cupsdCheckPolicy(DefaultPolicyPtr, con, NULL)) != HTTP_OK)
{
- send_http_error(con, status);
+ send_http_error(con, status, NULL);
return;
}
DefaultPolicyPtr,
con, sub->owner)) != HTTP_OK)
{
- send_http_error(con, status);
+ send_http_error(con, status, sub->dest);
return;
}
DefaultPolicyPtr,
con, NULL)) != HTTP_OK)
{
- send_http_error(con, status);
+ send_http_error(con, status, printer);
return;
}
if (!validate_user(job, con, job->username, username, sizeof(username)))
{
- send_http_error(con, HTTP_UNAUTHORIZED);
+ send_http_error(con, HTTP_UNAUTHORIZED, NULL);
return;
}
if ((status = cupsdCheckPolicy(dprinter->op_policy_ptr, con,
NULL)) != HTTP_OK)
{
- send_http_error(con, status);
+ send_http_error(con, status, dprinter);
return;
}
if (!validate_user(job, con, job->username, username, sizeof(username)))
{
- send_http_error(con, HTTP_UNAUTHORIZED);
+ send_http_error(con, HTTP_UNAUTHORIZED, NULL);
return;
}
if ((status = cupsdCheckPolicy(printer->op_policy_ptr, con, NULL)) != HTTP_OK)
{
- send_http_error(con, status);
+ send_http_error(con, status, printer);
return;
}
if (!validate_user(job, con, job->username, username, sizeof(username)))
{
- send_http_error(con, HTTP_UNAUTHORIZED);
+ send_http_error(con, HTTP_UNAUTHORIZED, NULL);
return;
}
DefaultPolicyPtr,
con, sub->owner)) != HTTP_OK)
{
- send_http_error(con, status);
+ send_http_error(con, status, sub->dest);
return;
}
if (!validate_user(job, con, job->username, username, sizeof(username)))
{
- send_http_error(con, HTTP_UNAUTHORIZED);
+ send_http_error(con, HTTP_UNAUTHORIZED, NULL);
return;
}
if (!validate_user(job, con, job->username, username, sizeof(username)))
{
- send_http_error(con, HTTP_UNAUTHORIZED);
+ send_http_error(con, HTTP_UNAUTHORIZED, NULL);
return;
}
*/
static void
-send_http_error(cupsd_client_t *con, /* I - Client connection */
- http_status_t status) /* I - HTTP status code */
+send_http_error(
+ cupsd_client_t *con, /* I - Client connection */
+ http_status_t status, /* I - HTTP status code */
+ cupsd_printer_t *printer) /* I - Printer, if any */
{
cupsdLogMessage(CUPSD_LOG_ERROR, "%s: %s",
ippOpString(con->request->request.op.operation_id),
httpStatus(status));
- cupsdSendError(con, status);
+ if (status == HTTP_UNAUTHORIZED &&
+ printer && printer->num_auth_info_required > 0 &&
+ !strcmp(printer->auth_info_required[0], "negotiate"))
+ cupsdSendError(con, status, AUTH_NEGOTIATE);
+ else
+ cupsdSendError(con, status, AUTH_NONE);
ippDelete(con->response);
con->response = NULL;
if ((status = cupsdCheckPolicy(DefaultPolicyPtr, con, NULL)) != HTTP_OK)
{
- send_http_error(con, status);
+ send_http_error(con, status, NULL);
return;
}
if (!validate_user(job, con, job->username, username, sizeof(username)))
{
- send_http_error(con, HTTP_UNAUTHORIZED);
+ send_http_error(con, HTTP_UNAUTHORIZED, NULL);
return;
}
if ((status = cupsdCheckPolicy(printer->op_policy_ptr, con, NULL)) != HTTP_OK)
{
- send_http_error(con, status);
+ send_http_error(con, status, printer);
return;
}
if ((status = cupsdCheckPolicy(printer->op_policy_ptr, con, NULL)) != HTTP_OK)
{
- send_http_error(con, status);
+ send_http_error(con, status, printer);
return;
}
if ((status = cupsdCheckPolicy(printer->op_policy_ptr, con, NULL)) != HTTP_OK)
{
- send_http_error(con, status);
+ send_http_error(con, status, printer);
return;
}
/*
- * End of "$Id: ipp.c 6370 2007-03-20 14:36:12Z mike $".
+ * End of "$Id: ipp.c 6383 2007-03-21 20:01:20Z mike $".
*/
/*
- * "$Id: job.c 6365 2007-03-19 20:56:57Z mike $"
+ * "$Id: job.c 6376 2007-03-21 06:39:10Z mike $"
*
* Job management routines for the Common UNIX Printing System (CUPS).
*
* cupsdStopAllJobs() - Stop all print jobs.
* cupsdStopJob() - Stop a print job.
* cupsdUnloadCompletedJobs() - Flush completed job history from memory.
- * cupsdUpdateJob() - Read a status update from a jobs filters.
* compare_active_jobs() - Compare the job IDs and priorities of two
* jobs.
* compare_jobs() - Compare the job IDs of two jobs.
* attribute...
* start_job() - Start a print job.
* unload_job() - Unload a job from memory.
+ * update_job() - Read a status update from a jobs filters.
*/
/*
static void set_hold_until(cupsd_job_t *job, time_t holdtime);
static void start_job(cupsd_job_t *job, cupsd_printer_t *printer);
static void unload_job(cupsd_job_t *job);
+static void update_job(cupsd_job_t *job);
/*
}
-/*
- * 'cupsdUpdateJob()' - Read a status update from a job's filters.
- */
-
-void
-cupsdUpdateJob(cupsd_job_t *job) /* I - Job to check */
-{
- int i; /* Looping var */
- int copies; /* Number of copies printed */
- char message[1024], /* Message text */
- *ptr; /* Pointer update... */
- int loglevel, /* Log level for message */
- event = 0; /* Events? */
-
-
- while ((ptr = cupsdStatBufUpdate(job->status_buffer, &loglevel,
- message, sizeof(message))) != NULL)
- {
- /*
- * Process page and printer state messages as needed...
- */
-
- if (loglevel == CUPSD_LOG_PAGE)
- {
- /*
- * Page message; send the message to the page_log file and update the
- * job sheet count...
- */
-
- if (job->sheets != NULL)
- {
- if (!strncasecmp(message, "total ", 6))
- {
- /*
- * Got a total count of pages from a backend or filter...
- */
-
- copies = atoi(message + 6);
- copies -= job->sheets->values[0].integer; /* Just track the delta */
- }
- else if (!sscanf(message, "%*d%d", &copies))
- copies = 1;
-
- job->sheets->values[0].integer += copies;
-
- if (job->printer->page_limit)
- {
- cupsd_quota_t *q = cupsdUpdateQuota(job->printer, job->username,
- copies, 0);
-
-#ifdef __APPLE__
- if (AppleQuotas && q->page_count == -3)
- {
- /*
- * Quota limit exceeded, cancel job in progress immediately...
- */
-
- cupsdLogMessage(CUPSD_LOG_INFO,
- "Job %d canceled: pages exceed user %s quota "
- "limit on printer %s (%s).",
- job->id, job->username, job->printer->name,
- job->printer->info);
-
- cupsdCancelJob(job, 1, IPP_JOB_CANCELED);
- return;
- }
-#endif /* __APPLE__ */
- }
- }
-
- cupsdLogPage(job, message);
-
- cupsdAddEvent(CUPSD_EVENT_JOB_PROGRESS, job->printer, job,
- "Printed %d page(s).", job->sheets->values[0].integer);
- }
- else if (loglevel == CUPSD_LOG_STATE)
- {
- cupsdSetPrinterReasons(job->printer, message);
- cupsdAddPrinterHistory(job->printer);
- event |= CUPSD_EVENT_PRINTER_STATE_CHANGED;
- }
- else if (loglevel == CUPSD_LOG_ATTR)
- {
- /*
- * Set attribute(s)...
- */
-
- int num_attrs; /* Number of attributes */
- cups_option_t *attrs; /* Attributes */
- const char *attr; /* Attribute */
-
-
- num_attrs = cupsParseOptions(message, 0, &attrs);
-
- if ((attr = cupsGetOption("auth-info-required", num_attrs,
- attrs)) != NULL)
- cupsdSetAuthInfoRequired(job->printer, attr, NULL);
-
- cupsFreeOptions(num_attrs, attrs);
- }
-#ifdef __APPLE__
- else if (!strncmp(message, "recoverable:", 12))
- {
- cupsdSetPrinterReasons(job->printer,
- "+com.apple.print.recoverable-warning");
-
- ptr = message + 12;
- while (isspace(*ptr & 255))
- ptr ++;
-
- cupsdSetString(&job->printer->recoverable, ptr);
- cupsdAddPrinterHistory(job->printer);
- event |= CUPSD_EVENT_PRINTER_STATE_CHANGED;
- }
- else if (!strncmp(message, "recovered:", 10))
- {
- cupsdSetPrinterReasons(job->printer,
- "-com.apple.print.recoverable-warning");
-
- ptr = message + 10;
- while (isspace(*ptr & 255))
- ptr ++;
-
- cupsdSetString(&job->printer->recoverable, ptr);
- cupsdAddPrinterHistory(job->printer);
- event |= CUPSD_EVENT_PRINTER_STATE_CHANGED;
- }
-#endif /* __APPLE__ */
- else if (loglevel <= CUPSD_LOG_INFO)
- {
- /*
- * Some message to show in the printer-state-message attribute...
- */
-
- strlcpy(job->printer->state_message, message,
- sizeof(job->printer->state_message));
- cupsdAddPrinterHistory(job->printer);
- event |= CUPSD_EVENT_PRINTER_STATE_CHANGED;
- }
-
- if (!strchr(job->status_buffer->buffer, '\n'))
- break;
- }
-
- if ((event & CUPSD_EVENT_PRINTER_STATE_CHANGED))
- cupsdAddEvent(CUPSD_EVENT_PRINTER_STATE_CHANGED, job->printer, NULL,
- (job->printer->type & CUPS_PRINTER_CLASS) ?
- "Class \"%s\" state changed." :
- "Printer \"%s\" state changed.",
- job->printer->name);
-
- if (ptr == NULL && !job->status_buffer->bufused)
- {
- /*
- * See if all of the filters and the backend have returned their
- * exit statuses.
- */
-
- for (i = 0; job->filters[i] < 0; i ++);
-
- if (job->filters[i])
- return;
-
- if (job->current_file >= job->num_files && job->backend > 0)
- return;
-
- /*
- * Handle the end of job stuff...
- */
-
- cupsdFinishJob(job);
- }
-}
-
-
/*
* 'compare_active_jobs()' - Compare the job IDs and priorities of two jobs.
*/
return;
}
- if (printer->raw && !strncmp(printer->device_uri, "file:", 5))
- {
- cupsdLogMessage(CUPSD_LOG_ERROR,
- "Job ID %d cannot be printed to raw queue pointing to "
- "a file!",
- job->id);
-
- strlcpy(printer->state_message, "Raw printers cannot use file: devices!",
- sizeof(printer->state_message));
- cupsdStopPrinter(printer, 1);
- cupsdAddPrinterHistory(printer);
- return;
- }
-
/*
* Figure out what filters are required to convert from
* the source to the destination type...
FilterLevel += job->cost;
/*
- * Add decompression filters, if any...
+ * Add decompression/raw filter as needed...
*/
- if (!printer->raw && job->compressions[job->current_file])
+ if ((!printer->raw && job->compressions[job->current_file]) ||
+ (!filters && !printer->remote &&
+ (job->num_files > 1 || !strncmp(printer->device_uri, "file:", 5))))
{
/*
* Add gziptoany filter to the front of the list...
job->state->values[0].integer = IPP_JOB_PROCESSING;
job->state_value = IPP_JOB_PROCESSING;
+
job->status = 0;
job->printer = printer;
printer->job = job;
+
cupsdSetPrinterState(printer, IPP_PRINTER_PROCESSING, 0);
if (job->current_file == 0)
envp[envc ++] = device_uri;
envp[envc ++] = printer_name;
- if (!printer->remote &&
+ if (!printer->remote && !printer->raw &&
(filter = (mime_filter_t *)cupsArrayLast(filters)) != NULL)
{
snprintf(final_content_type, sizeof(final_content_type),
free(argv);
- cupsdAddSelect(job->status_buffer->fd, (cupsd_selfunc_t)cupsdUpdateJob, NULL,
+ cupsdAddSelect(job->status_buffer->fd, (cupsd_selfunc_t)update_job, NULL,
job);
cupsdAddEvent(CUPSD_EVENT_JOB_STATE, job->printer, job, "Job #%d started.",
/*
- * End of "$Id: job.c 6365 2007-03-19 20:56:57Z mike $".
+ * 'update_job()' - Read a status update from a job's filters.
+ */
+
+void
+update_job(cupsd_job_t *job) /* I - Job to check */
+{
+ int i; /* Looping var */
+ int copies; /* Number of copies printed */
+ char message[1024], /* Message text */
+ *ptr; /* Pointer update... */
+ int loglevel, /* Log level for message */
+ event = 0; /* Events? */
+
+
+ while ((ptr = cupsdStatBufUpdate(job->status_buffer, &loglevel,
+ message, sizeof(message))) != NULL)
+ {
+ /*
+ * Process page and printer state messages as needed...
+ */
+
+ if (loglevel == CUPSD_LOG_PAGE)
+ {
+ /*
+ * Page message; send the message to the page_log file and update the
+ * job sheet count...
+ */
+
+ if (job->sheets != NULL)
+ {
+ if (!strncasecmp(message, "total ", 6))
+ {
+ /*
+ * Got a total count of pages from a backend or filter...
+ */
+
+ copies = atoi(message + 6);
+ copies -= job->sheets->values[0].integer; /* Just track the delta */
+ }
+ else if (!sscanf(message, "%*d%d", &copies))
+ copies = 1;
+
+ job->sheets->values[0].integer += copies;
+
+ if (job->printer->page_limit)
+ {
+ cupsd_quota_t *q = cupsdUpdateQuota(job->printer, job->username,
+ copies, 0);
+
+#ifdef __APPLE__
+ if (AppleQuotas && q->page_count == -3)
+ {
+ /*
+ * Quota limit exceeded, cancel job in progress immediately...
+ */
+
+ cupsdLogMessage(CUPSD_LOG_INFO,
+ "Job %d canceled: pages exceed user %s quota "
+ "limit on printer %s (%s).",
+ job->id, job->username, job->printer->name,
+ job->printer->info);
+
+ cupsdCancelJob(job, 1, IPP_JOB_CANCELED);
+ return;
+ }
+#else
+ (void)q;
+#endif /* __APPLE__ */
+ }
+ }
+
+ cupsdLogPage(job, message);
+
+ cupsdAddEvent(CUPSD_EVENT_JOB_PROGRESS, job->printer, job,
+ "Printed %d page(s).", job->sheets->values[0].integer);
+ }
+ else if (loglevel == CUPSD_LOG_STATE)
+ {
+ cupsdSetPrinterReasons(job->printer, message);
+ cupsdAddPrinterHistory(job->printer);
+ event |= CUPSD_EVENT_PRINTER_STATE_CHANGED;
+ }
+ else if (loglevel == CUPSD_LOG_ATTR)
+ {
+ /*
+ * Set attribute(s)...
+ */
+
+ int num_attrs; /* Number of attributes */
+ cups_option_t *attrs; /* Attributes */
+ const char *attr; /* Attribute */
+
+
+ num_attrs = cupsParseOptions(message, 0, &attrs);
+
+ if ((attr = cupsGetOption("auth-info-required", num_attrs,
+ attrs)) != NULL)
+ cupsdSetAuthInfoRequired(job->printer, attr, NULL);
+
+ cupsFreeOptions(num_attrs, attrs);
+ }
+#ifdef __APPLE__
+ else if (!strncmp(message, "recoverable:", 12))
+ {
+ cupsdSetPrinterReasons(job->printer,
+ "+com.apple.print.recoverable-warning");
+
+ ptr = message + 12;
+ while (isspace(*ptr & 255))
+ ptr ++;
+
+ cupsdSetString(&job->printer->recoverable, ptr);
+ cupsdAddPrinterHistory(job->printer);
+ event |= CUPSD_EVENT_PRINTER_STATE_CHANGED;
+ }
+ else if (!strncmp(message, "recovered:", 10))
+ {
+ cupsdSetPrinterReasons(job->printer,
+ "-com.apple.print.recoverable-warning");
+
+ ptr = message + 10;
+ while (isspace(*ptr & 255))
+ ptr ++;
+
+ cupsdSetString(&job->printer->recoverable, ptr);
+ cupsdAddPrinterHistory(job->printer);
+ event |= CUPSD_EVENT_PRINTER_STATE_CHANGED;
+ }
+#endif /* __APPLE__ */
+ else if (loglevel <= CUPSD_LOG_INFO)
+ {
+ /*
+ * Some message to show in the printer-state-message attribute...
+ */
+
+ strlcpy(job->printer->state_message, message,
+ sizeof(job->printer->state_message));
+ cupsdAddPrinterHistory(job->printer);
+ event |= CUPSD_EVENT_PRINTER_STATE_CHANGED;
+ }
+
+ if (!strchr(job->status_buffer->buffer, '\n'))
+ break;
+ }
+
+ if ((event & CUPSD_EVENT_PRINTER_STATE_CHANGED))
+ cupsdAddEvent(CUPSD_EVENT_PRINTER_STATE_CHANGED, job->printer, NULL,
+ (job->printer->type & CUPS_PRINTER_CLASS) ?
+ "Class \"%s\" state changed." :
+ "Printer \"%s\" state changed.",
+ job->printer->name);
+
+ if (ptr == NULL && !job->status_buffer->bufused)
+ {
+ /*
+ * See if all of the filters and the backend have returned their
+ * exit statuses.
+ */
+
+ for (i = 0; job->filters[i] < 0; i ++);
+
+ if (job->filters[i])
+ return;
+
+ if (job->current_file >= job->num_files && job->backend > 0)
+ return;
+
+ /*
+ * Handle the end of job stuff...
+ */
+
+ cupsdFinishJob(job);
+ }
+}
+
+
+/*
+ * End of "$Id: job.c 6376 2007-03-21 06:39:10Z mike $".
*/
/*
- * "$Id: job.h 6170 2007-01-02 17:26:41Z mike $"
+ * "$Id: job.h 6376 2007-03-21 06:39:10Z mike $"
*
* Print job definitions for the Common UNIX Printing System (CUPS) scheduler.
*
extern void cupsdSetJobPriority(cupsd_job_t *job, int priority);
extern void cupsdStopAllJobs(int force);
extern void cupsdStopJob(cupsd_job_t *job, int force);
-extern void cupsdUpdateJob(cupsd_job_t *job);
/*
- * End of "$Id: job.h 6170 2007-01-02 17:26:41Z mike $".
+ * End of "$Id: job.h 6376 2007-03-21 06:39:10Z mike $".
*/
/*
- * "$Id: printers.c 6354 2007-03-19 06:16:32Z mike $"
+ * "$Id: printers.c 6383 2007-03-21 20:01:20Z mike $"
*
* Printer routines for the Common UNIX Printing System (CUPS).
*
if ((end = strchr(values, ',')) == NULL)
end = values + strlen(values);
- if (!strncmp(values, "none", end - values))
+ if ((end - values) == 4 && !strncmp(values, "none", 4))
{
if (p->num_auth_info_required != 0 || *end)
return (0);
return (1);
}
- else if (!strncmp(values, "domain", end - values))
+ else if ((end - values) == 9 && !strncmp(values, "negotiate", 9))
+ {
+ if (p->num_auth_info_required != 0 || *end)
+ return (0);
+
+ p->auth_info_required[p->num_auth_info_required] = "negotiate";
+ p->num_auth_info_required ++;
+
+ return (1);
+ }
+ else if ((end - values) == 6 && !strncmp(values, "domain", 6))
{
p->auth_info_required[p->num_auth_info_required] = "domain";
p->num_auth_info_required ++;
}
- else if (!strncmp(values, "password", end - values))
+ else if ((end - values) == 8 && !strncmp(values, "password", 8))
{
p->auth_info_required[p->num_auth_info_required] = "password";
p->num_auth_info_required ++;
}
- else if (!strncmp(values, "username", end - values))
+ else if ((end - values) == 8 && !strncmp(values, "username", 8))
{
p->auth_info_required[p->num_auth_info_required] = "username";
p->num_auth_info_required ++;
return (1);
}
+ else if (!strcmp(attr->values[i].string.text, "negotiate"))
+ {
+ if (p->num_auth_info_required != 0 || attr->num_values != 1)
+ return (0);
+
+ p->auth_info_required[p->num_auth_info_required] = "negotiate";
+ p->num_auth_info_required ++;
+
+ return (1);
+ }
else if (!strcmp(attr->values[i].string.text, "domain"))
{
p->auth_info_required[p->num_auth_info_required] = "domain";
if (auth)
{
if (auth->type == AUTH_BASIC || auth->type == AUTH_BASICDIGEST)
+ {
auth_supported = "basic";
+ cupsdSetAuthInfoRequired(p, "username,password", NULL);
+ }
else if (auth->type == AUTH_DIGEST)
+ {
auth_supported = "digest";
+ cupsdSetAuthInfoRequired(p, "username,password", NULL);
+ }
+#ifdef HAVE_GSSAPI
+ else if (auth->type == AUTH_NEGOTIATE)
+ {
+ auth_supported = "negotiate";
+ cupsdSetAuthInfoRequired(p, "negotiate", NULL);
+ }
+#endif /* HAVE_GSSAPI */
if (auth->type != AUTH_NONE)
p->type |= CUPS_PRINTER_AUTHENTICATED;
/*
- * End of "$Id: printers.c 6354 2007-03-19 06:16:32Z mike $".
+ * End of "$Id: printers.c 6383 2007-03-21 20:01:20Z mike $".
*/
/*
- * "$Id: select.c 6166 2006-12-29 20:35:18Z mike $"
+ * "$Id: select.c 6376 2007-03-21 06:39:10Z mike $"
*
* Select abstraction functions for the Common UNIX Printing System (CUPS).
*
- * Copyright 2006 by Easy Software Products.
+ * Copyright 2006-2007 by Easy Software Products.
*
* These coded instructions, statements, and computer programs are the
* property of Easy Software Products and are protected by Federal
}
+#ifdef CUPSD_IS_SELECTING
/*
* 'cupsdIsSelecting()' - Determine whether we are monitoring a file
* descriptor.
{
return (find_fd(fd) != NULL);
}
+#endif /* CUPSD_IS_SELECTING */
/*
/*
- * End of "$Id: select.c 6166 2006-12-29 20:35:18Z mike $".
+ * End of "$Id: select.c 6376 2007-03-21 06:39:10Z mike $".
*/
/*
- * "$Id: subscriptions.c 6176 2007-01-03 15:28:30Z mike $"
+ * "$Id: subscriptions.c 6376 2007-03-21 06:39:10Z mike $"
*
* Subscription routines for the Common UNIX Printing System (CUPS) scheduler.
*
* cupsdLoadAllSubscriptions() - Load all subscriptions from the .conf file.
* cupsdSaveAllSubscriptions() - Save all subscriptions to the .conf file.
* cupsdStopAllNotifiers() - Stop all notifier processes.
- * cupsdUpdateNotifierStatus() - Read messages from notifiers.
* cupsd_compare_subscriptions() - Compare two subscriptions.
* cupsd_delete_event() - Delete a single event...
* cupsd_send_dbus() - Send a DBUS notification...
* cupsd_send_notification() - Send a notification for the specified
* event.
* cupsd_start_notifier() - Start a notifier subprocess...
+ * cupsd_update_notifier() - Read messages from notifiers.
*/
/*
static void cupsd_send_notification(cupsd_subscription_t *sub,
cupsd_event_t *event);
static void cupsd_start_notifier(cupsd_subscription_t *sub);
+static void cupsd_update_notifier(void);
/*
}
-/*
- * 'cupsdUpdateNotifierStatus()' - Read messages from notifiers.
- */
-
-void
-cupsdUpdateNotifierStatus(void)
-{
- char message[1024]; /* Pointer to message text */
- int loglevel; /* Log level for message */
-
-
- while (cupsdStatBufUpdate(NotifierStatusBuffer, &loglevel,
- message, sizeof(message)))
- if (!strchr(NotifierStatusBuffer->buffer, '\n'))
- break;
-}
-
-
/*
* 'cupsd_compare_subscriptions()' - Compare two subscriptions.
*/
NotifierStatusBuffer = cupsdStatBufNew(NotifierPipes[0], "[Notifier]");
- cupsdAddSelect(NotifierPipes[0], (cupsd_selfunc_t)cupsdUpdateNotifierStatus,
+ cupsdAddSelect(NotifierPipes[0], (cupsd_selfunc_t)cupsd_update_notifier,
NULL, NULL);
}
/*
- * End of "$Id: subscriptions.c 6176 2007-01-03 15:28:30Z mike $".
+ * 'cupsd_update_notifier()' - Read messages from notifiers.
+ */
+
+void
+cupsd_update_notifier(void)
+{
+ char message[1024]; /* Pointer to message text */
+ int loglevel; /* Log level for message */
+
+
+ while (cupsdStatBufUpdate(NotifierStatusBuffer, &loglevel,
+ message, sizeof(message)))
+ if (!strchr(NotifierStatusBuffer->buffer, '\n'))
+ break;
+}
+
+
+/*
+ * End of "$Id: subscriptions.c 6376 2007-03-21 06:39:10Z mike $".
*/
/*
- * "$Id: subscriptions.h 5672 2006-06-16 21:04:07Z mike $"
+ * "$Id: subscriptions.h 6376 2007-03-21 06:39:10Z mike $"
*
* Subscription definitions for the Common UNIX Printing System (CUPS) scheduler.
*
- * Copyright 1997-2006 by Easy Software Products, all rights reserved.
+ * Copyright 1997-2007 by Easy Software Products, all rights reserved.
*
* These coded instructions, statements, and computer programs are the
* property of Easy Software Products and are protected by Federal
extern void cupsdLoadAllSubscriptions(void);
extern void cupsdSaveAllSubscriptions(void);
extern void cupsdStopAllNotifiers(void);
-extern void cupsdUpdateNotifierStatus(void);
/*
- * End of "$Id: subscriptions.h 5672 2006-06-16 21:04:07Z mike $".
+ * End of "$Id: subscriptions.h 6376 2007-03-21 06:39:10Z mike $".
*/
/*
- * "$Id: testdirsvc.c 5301 2006-03-17 23:44:33Z mike $"
+ * "$Id: testdirsvc.c 6376 2007-03-21 06:39:10Z mike $"
*
* Browsing test program for the Common UNIX Printing System (CUPS).
*
- * Copyright 1997-2005 by Easy Software Products, all rights reserved.
+ * Copyright 1997-2007 by Easy Software Products, all rights reserved.
*
* These coded instructions, statements, and computer programs are the
* property of Easy Software Products and are protected by Federal
* Local functions...
*/
-void usage(void);
+static void usage(void);
/*
* 'usage()' - Show program usage...
*/
-void
+static void
usage(void)
{
puts("Usage: testdirsvc [-c] [-i interval] [-l lease-duration] "
/*
- * End of "$Id: testdirsvc.c 5301 2006-03-17 23:44:33Z mike $".
+ * End of "$Id: testdirsvc.c 6376 2007-03-21 06:39:10Z mike $".
*/
/*
- * "$Id: testsub.c 5938 2006-09-11 18:23:46Z mike $"
+ * "$Id: testsub.c 6376 2007-03-21 06:39:10Z mike $"
*
* Scheduler notification tester for the Common UNIX Printing System (CUPS).
*
- * Copyright 2006 by Easy Software Products.
+ * Copyright 2006-2007 by Easy Software Products.
*
* These coded instructions, statements, and computer programs are the
* property of Easy Software Products and are protected by Federal
* Local functions...
*/
-void print_attributes(ipp_t *ipp, int indent);
+static void print_attributes(ipp_t *ipp, int indent);
static void sigterm_handler(int sig);
static void usage(void);
* 'print_attributes()' - Print the attributes in a request...
*/
-void
+static void
print_attributes(ipp_t *ipp, /* I - IPP request */
int indent) /* I - Indentation */
{
/*
- * End of "$Id: testsub.c 5938 2006-09-11 18:23:46Z mike $".
+ * End of "$Id: testsub.c 6376 2007-03-21 06:39:10Z mike $".
*/
#
-# "$Id: 4.2-cups-printer-ops.test 5831 2006-08-16 19:28:09Z mike $"
+# "$Id: 4.2-cups-printer-ops.test 6379 2007-03-21 14:57:22Z mike $"
#
# Verify that the CUPS printer operations work.
#
ATTR name requesting-user-name $user
GROUP subscription
- ATTR uri notify-recipient testnotify://
+ ATTR uri notify-recipient-uri testnotify://
ATTR keyword notify-events printer-added,printer-modified,printer-deleted
# What statuses are OK?
}
#
-# End of "$Id: 4.2-cups-printer-ops.test 5831 2006-08-16 19:28:09Z mike $"
+# End of "$Id: 4.2-cups-printer-ops.test 6379 2007-03-21 14:57:22Z mike $"
#
#
-# "$Id: 4.3-job-ops.test 5493 2006-05-05 16:33:57Z mike $"
+# "$Id: 4.3-job-ops.test 6379 2007-03-21 14:57:22Z mike $"
#
# Verify that the IPP job operations work.
#
ATTR name requesting-user-name $user
GROUP subscription
- ATTR uri notify-recipient testnotify
+ ATTR uri notify-recipient-uri testnotify
FILE testfile.jpg
}
#
-# End of "$Id: 4.3-job-ops.test 5493 2006-05-05 16:33:57Z mike $"
+# End of "$Id: 4.3-job-ops.test 6379 2007-03-21 14:57:22Z mike $"
#
#
-# "$Id: 4.4-subscription-ops.test 5831 2006-08-16 19:28:09Z mike $"
+# "$Id: 4.4-subscription-ops.test 6379 2007-03-21 14:57:22Z mike $"
#
# Verify that the CUPS subscription operations work.
#
ATTR uri printer-uri $method://$hostname:$port/printers/Test1
GROUP subscription
- ATTR uri notify-recipient testnotify://
+ ATTR uri notify-recipient-uri testnotify://
ATTR keyword notify-events printer-state-changed
ATTR integer notify-lease-duration 5
ATTR uri printer-uri $method://$hostname:$port/printers/Test1
GROUP subscription
- ATTR uri notify-recipient testnotify://
+ ATTR uri notify-recipient-uri testnotify://
ATTR keyword notify-events printer-state-changed
ATTR integer notify-lease-duration 5
GROUP subscription
- ATTR uri notify-recipient testnotify://
+ ATTR uri notify-recipient-uri testnotify://
ATTR keyword notify-events printer-config-changed
ATTR integer notify-lease-duration 5
}
#
-# End of "$Id: 4.4-subscription-ops.test 5831 2006-08-16 19:28:09Z mike $"
+# End of "$Id: 4.4-subscription-ops.test 6379 2007-03-21 14:57:22Z mike $"
#
#!/bin/sh
#
-# "$Id: run-stp-tests.sh 6297 2007-02-21 02:24:16Z mike $"
+# "$Id: run-stp-tests.sh 6380 2007-03-21 15:18:53Z mike $"
#
# Perform the complete set of IPP compliance tests specified in the
# CUPS Software Test Plan.
#
-# Copyright 1997-2006 by Easy Software Products, all rights reserved.
+# Copyright 1997-2007 by Easy Software Products, all rights reserved.
#
# These coded instructions, statements, and computer programs are the
# property of Easy Software Products and are protected by Federal
echo ""
#
-# End of "$Id: run-stp-tests.sh 6297 2007-02-21 02:24:16Z mike $"
+# End of "$Id: run-stp-tests.sh 6380 2007-03-21 15:18:53Z mike $"
#
<HTML>
<HEAD>
<META NAME="Description" CONTENT="Common UNIX Printing System Software Test Report">
- <META NAME="COPYRIGHT" CONTENT="Copyright 1997-2006, All Rights Reserved">
- <META NAME="DOCNUMBER" CONTENT="CUPS-STR-1.2">
+ <META NAME="COPYRIGHT" CONTENT="Copyright 1997-2007, All Rights Reserved">
+ <META NAME="DOCNUMBER" CONTENT="CUPS-STR-1.3">
<META NAME="Author" CONTENT="Easy Software Products">
- <TITLE>CUPS 1.2 Software Test Report</TITLE>
+ <TITLE>CUPS 1.3 Software Test Report</TITLE>
</HEAD>
<BODY>
-<H1>CUPS 1.2 Software Test Report</H1>
+<H1>CUPS 1.3 Software Test Report</H1>
<P>This software test report provides detailed test results that
are used to evaluate the stability and compliance of the Common
-UNIX Printing System ("CUPS") Version 1.2.
+UNIX Printing System ("CUPS") Version 1.3.
<H2>Document Overview</H2>