/*
- * "$Id: ipp.c 5383 2006-04-07 15:36:10Z mike $"
+ * "$Id: ipp.c 5970 2006-09-19 20:11:08Z mike $"
*
* IPP routines for the Common UNIX Printing System (CUPS) scheduler.
*
* set_printer_defaults() - Set printer default options from a request.
* start_printer() - Start a printer.
* stop_printer() - Stop a printer.
+ * url_encode_attr() - URL-encode a string attribute.
* user_allowed() - See if a user is allowed to print to a queue.
* validate_job() - Validate printer options and destination.
* validate_name() - Make sure the printer name only contains
cupsd_printer_t *printer);
static void start_printer(cupsd_client_t *con, ipp_attribute_t *uri);
static void stop_printer(cupsd_client_t *con, ipp_attribute_t *uri);
+static void url_encode_attr(ipp_attribute_t *attr, char *buffer,
+ int bufsize);
static int user_allowed(cupsd_printer_t *p, const char *username);
static void validate_job(cupsd_client_t *con, ipp_attribute_t *uri);
static int validate_name(const char *name);
if (cupsdSendHeader(con, HTTP_OK, "application/ipp"))
{
+#ifdef CUPSD_USE_CHUNKING
+ /*
+ * Because older versions of CUPS (1.1.17 and older) and some IPP
+ * clients do not implement chunking properly, we cannot use
+ * chunking by default. This may become the default in future
+ * CUPS releases, or we might add a configuration directive for
+ * it.
+ */
+
if (con->http.version == HTTP_1_1)
{
- con->http.data_encoding = HTTP_ENCODE_CHUNKED;
+ if (httpPrintf(HTTP(con), "Transfer-Encoding: chunked\r\n\r\n") < 0)
+ return (0);
+
+ if (cupsdFlushHeader(con) < 0)
+ return (0);
- httpPrintf(HTTP(con), "Transfer-Encoding: chunked\r\n\r\n");
+ con->http.data_encoding = HTTP_ENCODE_CHUNKED;
}
else
+#endif /* CUPSD_USE_CHUNKING */
{
- con->http.data_encoding = HTTP_ENCODE_LENGTH;
- con->http.data_remaining = ippLength(con->response);
+ size_t length; /* Length of response */
- if (con->http.data_remaining < INT_MAX)
- con->http._data_remaining = con->http.data_remaining;
- else
- con->http._data_remaining = INT_MAX;
- httpPrintf(HTTP(con), "Content-Length: " CUPS_LLFMT "\r\n\r\n",
- CUPS_LLCAST con->http.data_remaining);
+ length = ippLength(con->response);
+
+ if (httpPrintf(HTTP(con), "Content-Length: " CUPS_LLFMT "\r\n\r\n",
+ CUPS_LLCAST length) < 0)
+ return (0);
+
+ if (cupsdFlushHeader(con) < 0)
+ return (0);
+
+ con->http.data_encoding = HTTP_ENCODE_LENGTH;
+ con->http.data_remaining = length;
}
cupsdLogMessage(CUPSD_LOG_DEBUG2,
cupsd_printer_t *pclass, /* Class */
*member; /* Member printer/class */
cups_ptype_t dtype; /* Destination type */
- const char *dest; /* Printer or class name */
ipp_attribute_t *attr; /* Printer attribute */
int modify; /* Non-zero if we just modified */
char newname[IPP_MAX_NAME]; /* New class name */
sizeof(method), username, sizeof(username), host,
sizeof(host), &port, resource, sizeof(resource));
- if ((dest = cupsdValidateDest(host, resource, &dtype, &member)) == NULL)
+ if (!cupsdValidateDest(host, resource, &dtype, &member))
{
/*
* Bad URI...
if (!compressions || !filetypes)
{
- cupsdCancelJob(job, 1);
+ cupsdCancelJob(job, 1, IPP_JOB_ABORTED);
send_ipp_status(con, IPP_INTERNAL_ERROR,
_("Unable to allocate memory for file types!"));
ippAddInteger(job->attrs, IPP_TAG_JOB, IPP_TAG_INTEGER, "job-id", job->id);
job->state = ippAddInteger(job->attrs, IPP_TAG_JOB, IPP_TAG_ENUM,
"job-state", IPP_JOB_STOPPED);
- job->state_value = job->state->values[0].integer;
+ job->state_value = (ipp_jstate_t)job->state->values[0].integer;
job->sheets = ippAddInteger(job->attrs, IPP_TAG_JOB, IPP_TAG_INTEGER,
"job-media-sheets-completed", 0);
ippAddString(job->attrs, IPP_TAG_JOB, IPP_TAG_URI, "job-printer-uri", NULL,
cupsdLogMessage(CUPSD_LOG_DEBUG2, "add_job_state_reasons(%p[%d], %d)",
con, con->http.fd, job ? job->id : 0);
- switch (job ? job->state_value : IPP_JOB_CANCELLED)
+ switch (job ? job->state_value : IPP_JOB_CANCELED)
{
case IPP_JOB_PENDING :
dest = cupsdFindDest(job->dest);
"job-state-reasons", NULL, "job-stopped");
break;
- case IPP_JOB_CANCELLED :
+ case IPP_JOB_CANCELED :
ippAddString(con->response, IPP_TAG_JOB, IPP_TAG_KEYWORD,
"job-state-reasons", NULL, "job-canceled-by-user");
break;
cupsd_job_t *job) /* I - Job */
{
char uuid[1024]; /* job-uuid string */
- ipp_attribute_t *attr; /* job-uuid attribute */
_cups_md5_state_t md5state; /* MD5 state */
unsigned char md5sum[16]; /* MD5 digest/sum */
* First see if the job already has a job-uuid attribute; if so, return...
*/
- if ((attr = ippFindAttribute(job->attrs, "job-uuid", IPP_TAG_URI)) != NULL)
+ if (ippFindAttribute(job->attrs, "job-uuid", IPP_TAG_URI))
return;
/*
cupsdCancelJobs(NULL, username, purge);
cupsdLogMessage(CUPSD_LOG_INFO, "All jobs were %s by \"%s\".",
- purge ? "purged" : "cancelled", get_username(con));
+ purge ? "purged" : "canceled", get_username(con));
}
else
{
cupsdCancelJobs(dest, username, purge);
cupsdLogMessage(CUPSD_LOG_INFO, "All jobs on \"%s\" were %s by \"%s\".",
- dest, purge ? "purged" : "cancelled", get_username(con));
+ dest, purge ? "purged" : "canceled", get_username(con));
}
con->response->request.status.status_code = IPP_OK;
}
/*
- * See if the job is already completed, cancelled, or aborted; if so,
+ * See if the job is already completed, canceled, or aborted; if so,
* we can't cancel...
*/
- if (job->state_value >= IPP_JOB_CANCELLED)
+ if (job->state_value >= IPP_JOB_CANCELED)
{
switch (job->state_value)
{
- case IPP_JOB_CANCELLED :
+ case IPP_JOB_CANCELED :
send_ipp_status(con, IPP_NOT_POSSIBLE,
- _("Job #%d is already cancelled - can\'t cancel."),
+ _("Job #%d is already canceled - can\'t cancel."),
jobid);
break;
* Cancel the job and return...
*/
- cupsdAddEvent(CUPSD_EVENT_JOB_COMPLETED, job->printer, job,
- "Job cancelled by \"%s\".", username);
-
- cupsdCancelJob(job, 0);
+ cupsdCancelJob(job, 0, IPP_JOB_CANCELED);
cupsdCheckJobs();
- cupsdLogMessage(CUPSD_LOG_INFO, "Job %d was cancelled by \"%s\".", jobid,
+ cupsdLogMessage(CUPSD_LOG_INFO, "Job %d was canceled by \"%s\".", jobid,
username);
con->response->request.status.status_code = IPP_OK;
{
httpAssembleURIf(HTTP_URI_CODING_ALL, printer_uri, sizeof(printer_uri),
"ipp", NULL, con->servername, con->serverport,
- "/printers/%s", printer->name);
+ (printer->type & CUPS_PRINTER_CLASS) ?
+ "/classes/%s" : "/printers/%s", printer->name);
ippAddString(con->response, IPP_TAG_PRINTER, IPP_TAG_URI,
"printer-uri-supported", NULL, printer_uri);
cupsdLogMessage(CUPSD_LOG_DEBUG2, "printer-uri-supported=\"%s\"",
*/
ippAddString(con->response, IPP_TAG_SUBSCRIPTION,
- IPP_TAG_KEYWORD | IPP_TAG_COPY,
+ (ipp_tag_t)(IPP_TAG_KEYWORD | IPP_TAG_COPY),
"notify-events", NULL, name);
}
else
count ++;
attr = ippAddStrings(con->response, IPP_TAG_SUBSCRIPTION,
- IPP_TAG_KEYWORD | IPP_TAG_COPY,
+ (ipp_tag_t)(IPP_TAG_KEYWORD | IPP_TAG_COPY),
"notify-events", count, NULL, NULL);
for (mask = 1, count = 0; mask < CUPSD_EVENT_ALL; mask <<= 1)
cupsArrayAdd(ra, "notify-lease-duration-default");
cupsArrayAdd(ra, "notify-lease-duration-supported");
cupsArrayAdd(ra, "notify-max-events-supported");
- cupsArrayAdd(ra, "notify-notify-events-default");
- cupsArrayAdd(ra, "notify-notify-events-supported");
+ cupsArrayAdd(ra, "notify-events-default");
+ cupsArrayAdd(ra, "notify-events-supported");
cupsArrayAdd(ra, "notify-pull-method-supported");
cupsArrayAdd(ra, "notify-schemes-supported");
cupsArrayAdd(ra, "operations-supported");
http_status_t status; /* Policy status */
int i; /* Looping var */
ipp_attribute_t *attr; /* Current attribute */
- const char *dest; /* Destination */
cups_ptype_t dtype; /* Destination type (printer or class) */
- char method[HTTP_MAX_URI],
- /* Method portion of URI */
+ char scheme[HTTP_MAX_URI],
+ /* Scheme portion of URI */
userpass[HTTP_MAX_URI],
/* Username portion of URI */
host[HTTP_MAX_URI],
"cupsdCreateSubscription(con=%p(%d), uri=\"%s\")",
con, con->http.fd, uri->values[0].string.text);
- httpSeparateURI(HTTP_URI_CODING_ALL, uri->values[0].string.text, method,
- sizeof(method), userpass, sizeof(userpass), host,
+ httpSeparateURI(HTTP_URI_CODING_ALL, uri->values[0].string.text, scheme,
+ sizeof(scheme), userpass, sizeof(userpass), host,
sizeof(host), &port, resource, sizeof(resource));
if (!strcmp(resource, "/"))
{
- dest = NULL;
dtype = (cups_ptype_t)0;
printer = NULL;
}
else if (!strncmp(resource, "/printers", 9) && strlen(resource) <= 10)
{
- dest = NULL;
dtype = (cups_ptype_t)0;
printer = NULL;
}
else if (!strncmp(resource, "/classes", 8) && strlen(resource) <= 9)
{
- dest = NULL;
dtype = CUPS_PRINTER_CLASS;
printer = NULL;
}
- else if ((dest = cupsdValidateDest(host, resource, &dtype, &printer)) == NULL)
+ else if (!cupsdValidateDest(host, resource, &dtype, &printer))
{
/*
* Bad URI...
{
if (!strcmp(attr->name, "notify-recipient") &&
attr->value_tag == IPP_TAG_URI)
+ {
+ /*
+ * Validate the recipient scheme against the ServerBin/notifier
+ * directory...
+ */
+
+ char notifier[1024]; /* Notifier filename */
+
+
recipient = attr->values[0].string.text;
+
+ if (httpSeparateURI(HTTP_URI_CODING_ALL, recipient,
+ scheme, sizeof(scheme), userpass, sizeof(userpass),
+ host, sizeof(host), &port,
+ resource, sizeof(resource)) < HTTP_URI_OK)
+ {
+ send_ipp_status(con, IPP_NOT_POSSIBLE,
+ _("Bad notify-recipient URI \"%s\"!"), recipient);
+ ippAddInteger(con->response, IPP_TAG_SUBSCRIPTION, IPP_TAG_ENUM,
+ "notify-status-code", IPP_URI_SCHEME);
+ return;
+ }
+
+ snprintf(notifier, sizeof(notifier), "%s/notifier/%s", ServerBin,
+ scheme);
+ if (access(notifier, X_OK))
+ {
+ send_ipp_status(con, IPP_NOT_POSSIBLE,
+ _("notify-recipient URI \"%s\" uses unknown scheme!"),
+ recipient);
+ ippAddInteger(con->response, IPP_TAG_SUBSCRIPTION, IPP_TAG_ENUM,
+ "notify-status-code", IPP_URI_SCHEME);
+ return;
+ }
+ }
else if (!strcmp(attr->name, "notify-pull-method") &&
attr->value_tag == IPP_TAG_KEYWORD)
+ {
pullmethod = attr->values[0].string.text;
+
+ if (strcmp(pullmethod, "ippget"))
+ {
+ send_ipp_status(con, IPP_NOT_POSSIBLE,
+ _("Bad notify-pull-method \"%s\"!"), pullmethod);
+ ippAddInteger(con->response, IPP_TAG_SUBSCRIPTION, IPP_TAG_ENUM,
+ "notify-status-code", IPP_ATTRIBUTES);
+ return;
+ }
+ }
else if (!strcmp(attr->name, "notify-charset") &&
attr->value_tag == IPP_TAG_CHARSET &&
strcmp(attr->values[0].string.text, "us-ascii") &&
get_devices(cupsd_client_t *con) /* I - Client connection */
{
http_status_t status; /* Policy status */
- int i; /* Looping var */
ipp_attribute_t *limit, /* Limit attribute */
*requested; /* requested-attributes attribute */
char command[1024], /* cups-deviced command */
options[1024], /* Options to pass to command */
- attrs[1024], /* String for requested attributes */
- *aptr; /* Pointer into string */
- int alen; /* Length of attribute value */
+ requested_str[256];
+ /* String for requested attributes */
cupsdLogMessage(CUPSD_LOG_DEBUG2, "get_devices(%p[%d])", con, con->http.fd);
IPP_TAG_KEYWORD);
if (requested)
- {
- for (i = 0, aptr = attrs; i < requested->num_values; i ++)
- {
- /*
- * Check that we have enough room...
- */
-
- alen = strlen(requested->values[i].string.text);
- if (alen > (sizeof(attrs) - (aptr - attrs) - 2))
- break;
-
- /*
- * Put commas between values...
- */
-
- if (i)
- *aptr++ = ',';
-
- /*
- * Add the value to the end of the string...
- */
-
- strcpy(aptr, requested->values[i].string.text);
- aptr += alen;
- }
-
- /*
- * If we have more attribute names than will fit, default to "all"...
- */
-
- if (i < requested->num_values)
- strcpy(attrs, "all");
- }
+ url_encode_attr(requested, requested_str, sizeof(requested_str));
else
- strcpy(attrs, "all");
+ strlcpy(requested_str, "requested-attributes=all", sizeof(requested_str));
snprintf(command, sizeof(command), "%s/daemon/cups-deviced", ServerBin);
snprintf(options, sizeof(options),
- "%d+%d+%d+requested-attributes=%s",
+ "%d+%d+%d+%s",
con->request->request.op.request_id,
limit ? limit->values[0].integer : 0, (int)User,
- attrs);
+ requested_str);
if (cupsdSendCommand(con, command, options, 1))
{
get_ppds(cupsd_client_t *con) /* I - Client connection */
{
http_status_t status; /* Policy status */
- int i; /* Looping var */
ipp_attribute_t *limit, /* Limit attribute */
*make, /* ppd-make attribute */
*requested; /* requested-attributes attribute */
char command[1024], /* cups-deviced command */
options[1024], /* Options to pass to command */
- attrs[1024], /* String for requested attributes */
- *aptr; /* Pointer into string */
- int alen; /* Length of attribute value */
+ requested_str[256],
+ /* String for requested attributes */
+ make_str[256]; /* Escaped ppd-make string */
cupsdLogMessage(CUPSD_LOG_DEBUG2, "get_ppds(%p[%d])", con, con->http.fd);
IPP_TAG_KEYWORD);
if (requested)
- {
- for (i = 0, aptr = attrs; i < requested->num_values; i ++)
- {
- /*
- * Check that we have enough room...
- */
-
- alen = strlen(requested->values[i].string.text);
- if (alen > (sizeof(attrs) - (aptr - attrs) - 2))
- break;
-
- /*
- * Put commas between values...
- */
-
- if (i)
- *aptr++ = ',';
-
- /*
- * Add the value to the end of the string...
- */
-
- strcpy(aptr, requested->values[i].string.text);
- aptr += alen;
- }
-
- /*
- * If we have more attribute names than will fit, default to "all"...
- */
+ url_encode_attr(requested, requested_str, sizeof(requested_str));
+ else
+ strlcpy(requested_str, "requested-attributes=all", sizeof(requested_str));
- if (i < requested->num_values)
- strcpy(attrs, "all");
- }
+ if (make)
+ url_encode_attr(make, make_str, sizeof(make_str));
else
- strcpy(attrs, "all");
+ make_str[0] = '\0';
snprintf(command, sizeof(command), "%s/daemon/cups-driverd", ServerBin);
- snprintf(options, sizeof(options),
- "list+%d+%d+requested-attributes=%s%s%s",
+ snprintf(options, sizeof(options), "list+%d+%d+%s%s%s",
con->request->request.op.request_id,
limit ? limit->values[0].integer : 0,
- attrs,
- make ? "%20ppd-make=" : "",
- make ? make->values[0].string.text : "");
+ requested_str, make ? "%20" : "", make_str);
if (cupsdSendCommand(con, command, options, 0))
{
ipp_attribute_t *uri) /* I - Printer URI */
{
http_status_t status; /* Policy status */
- const char *dest; /* Destination */
cups_ptype_t dtype; /* Destination type (printer or class) */
char method[HTTP_MAX_URI],
/* Method portion of URI */
sizeof(method), username, sizeof(username), host,
sizeof(host), &port, resource, sizeof(resource));
- if ((dest = cupsdValidateDest(host, resource, &dtype, &printer)) == NULL)
+ if (!cupsdValidateDest(host, resource, &dtype, &printer))
{
/*
* Bad URI...
cupsdHoldJob(job);
+ cupsdAddEvent(CUPSD_EVENT_JOB_STATE, job->printer, job,
+ "Job held by user.");
+
if ((newattr = ippFindAttribute(con->request, "job-hold-until",
IPP_TAG_KEYWORD)) == NULL)
newattr = ippFindAttribute(con->request, "job-hold-until", IPP_TAG_NAME);
*/
cupsdSetJobHoldUntil(job, attr->values[0].string.text);
+
+ cupsdAddEvent(CUPSD_EVENT_JOB_CONFIG_CHANGED, job->printer, job,
+ "Job job-hold-until value changed by user.");
}
cupsdLogMessage(CUPSD_LOG_INFO, "Job %d was held by \"%s\".", jobid,
ipp_attribute_t *attr; /* Current attribute */
int jobid; /* Job ID */
cupsd_job_t *job; /* Current job */
- const char *src, /* Source printer/class */
- *dest; /* Destination */
+ const char *src; /* Source printer/class */
cups_ptype_t stype, /* Source type (printer or class) */
dtype; /* Destination type (printer or class) */
char method[HTTP_MAX_URI], /* Method portion of URI */
sizeof(method), username, sizeof(username), host,
sizeof(host), &port, resource, sizeof(resource));
- if ((dest = cupsdValidateDest(host, resource, &dtype, &dprinter)) == NULL)
+ if (!cupsdValidateDest(host, resource, &dtype, &dprinter))
{
/*
* Bad URI...
* See if we need to add the ending sheet...
*/
+ attr = ippFindAttribute(job->attrs, "job-sheets", IPP_TAG_NAME);
+
if (!(printer->type & (CUPS_PRINTER_REMOTE | CUPS_PRINTER_IMPLICIT)) &&
- attr->num_values > 1)
+ attr && attr->num_values > 1)
{
/*
* Yes...
attr->value_tag = IPP_TAG_KEYWORD;
attr->values[0].string.text = _cupsStrAlloc("no-hold");
+
+ cupsdAddEvent(CUPSD_EVENT_JOB_CONFIG_CHANGED, job->printer, job,
+ "Job job-hold-until value changed by user.");
}
/*
cupsdReleaseJob(job);
+ cupsdAddEvent(CUPSD_EVENT_JOB_STATE, job->printer, job,
+ "Job released by user.");
+
cupsdLogMessage(CUPSD_LOG_INFO, "Job %d was released by \"%s\".", jobid,
username);
cupsdLoadJob(job);
- if (!job->attrs ||job->num_files == 0)
+ if (!job->attrs || job->num_files == 0)
{
/*
* Nope - return a "not possible" error...
return;
}
+ printer = cupsdFindDest(job->dest);
+
/*
* See if the job is owned by the requesting user...
*/
return;
}
- printer = cupsdFindDest(job->dest);
-
if (printer->filetypes && !cupsArrayFind(printer->filetypes, filetype))
{
snprintf(mimetype, sizeof(mimetype), "%s/%s", filetype->super,
ippAddInteger(con->response, IPP_TAG_JOB, IPP_TAG_INTEGER, "job-id", jobid);
ippAddInteger(con->response, IPP_TAG_JOB, IPP_TAG_ENUM, "job-state",
- job ? job->state_value : IPP_JOB_CANCELLED);
+ job ? job->state_value : IPP_JOB_CANCELED);
add_job_state_reasons(con, job);
con->response->request.status.status_code = IPP_OK;
_cupsLangString(con->language, message), ap);
va_end(ap);
- cupsdLogMessage(status >= IPP_BAD_REQUEST ? CUPSD_LOG_ERROR : CUPSD_LOG_INFO,
- "%s %s: %s",
+ cupsdLogMessage(CUPSD_LOG_DEBUG, "%s %s: %s",
ippOpString(con->request->request.op.operation_id),
ippErrorString(status), formatted);
}
else
- cupsdLogMessage(status >= IPP_BAD_REQUEST ? CUPSD_LOG_ERROR : CUPSD_LOG_INFO,
- "%s %s",
+ cupsdLogMessage(CUPSD_LOG_DEBUG, "%s %s",
ippOpString(con->request->request.op.operation_id),
ippErrorString(status));
resource[HTTP_MAX_URI];
/* Resource portion of URI */
int port; /* Port portion of URI */
+ int event; /* Events? */
cupsdLogMessage(CUPSD_LOG_DEBUG2, "set_job_attrs(%p[%d], %s)", con,
cupsdLoadJob(job);
+ event = 0;
+
for (attr = con->request->attrs; attr; attr = attr->next)
{
if (attr->group_tag != IPP_TAG_JOB || !attr->name)
return;
}
else if (con->response->request.status.status_code == IPP_OK)
+ {
cupsdSetJobPriority(job, attr->values[0].integer);
+ event |= CUPSD_EVENT_JOB_CONFIG_CHANGED;
+ }
}
else if (!strcmp(attr->name, "job-state"))
{
else if (con->response->request.status.status_code == IPP_OK)
{
job->state->values[0].integer = attr->values[0].integer;
- job->state_value = attr->values[0].integer;
+ job->state_value = (ipp_jstate_t)attr->values[0].integer;
+
+ event |= CUPSD_EVENT_JOB_STATE;
}
break;
}
break;
- case IPP_JOB_CANCELLED :
+ case IPP_JOB_CANCELED :
case IPP_JOB_ABORTED :
case IPP_JOB_COMPLETED :
if (job->state_value > IPP_JOB_PROCESSING)
return;
}
else if (con->response->request.status.status_code == IPP_OK)
- {
- cupsdCancelJob(job, 0);
-
- if (JobHistory)
- {
- job->state->values[0].integer = attr->values[0].integer;
- job->state_value = attr->values[0].integer;
- cupsdSaveJob(job);
- }
- }
+ cupsdCancelJob(job, 0, (ipp_jstate_t)attr->values[0].integer);
break;
}
}
cupsdReleaseJob(job);
else
cupsdHoldJob(job);
+
+ event |= CUPSD_EVENT_JOB_CONFIG_CHANGED | CUPSD_EVENT_JOB_STATE;
}
}
else if (attr->value_tag == IPP_TAG_DELETEATTR)
job->attrs->last = job->attrs->prev;
_ippFreeAttr(attr2);
+
+ event |= CUPSD_EVENT_JOB_CONFIG_CHANGED;
}
}
else
*/
copy_attribute(job->attrs, attr, 0);
+
+ event |= CUPSD_EVENT_JOB_CONFIG_CHANGED;
}
}
cupsdSaveJob(job);
+ /*
+ * Send events as needed...
+ */
+
+ if (event & CUPSD_EVENT_JOB_STATE)
+ cupsdAddEvent(CUPSD_EVENT_JOB_STATE, job->printer, job,
+ job->state_value == IPP_JOB_HELD ?
+ "Job held by user." : "Job restarted by user.");
+
+ if (event & CUPSD_EVENT_JOB_CONFIG_CHANGED)
+ cupsdAddEvent(CUPSD_EVENT_JOB_CONFIG_CHANGED, job->printer, job,
+ "Job options changed by user.");
+
/*
* Start jobs if possible...
*/
}
else if (!strcmp(attr->name, "document-format-default") ||
!strcmp(attr->name, "notify-lease-duration-default") ||
- !strcmp(attr->name, "notify-notify-events-default"))
+ !strcmp(attr->name, "notify-events-default"))
continue;
/*
cupsdStartPrinter(printer, 1);
if (dtype & CUPS_PRINTER_CLASS)
- {
cupsdLogMessage(CUPSD_LOG_INFO, "Class \"%s\" started by \"%s\".", name,
get_username(con));
- cupsdAddEvent(CUPSD_EVENT_PRINTER_MODIFIED, printer, NULL,
- "Class \"%s\" started by \"%s\".", name, get_username(con));
- }
else
- {
cupsdLogMessage(CUPSD_LOG_INFO, "Printer \"%s\" started by \"%s\".", name,
get_username(con));
- cupsdAddEvent(CUPSD_EVENT_PRINTER_MODIFIED, printer, NULL,
- "Printer \"%s\" started by \"%s\".", name, get_username(con));
- }
cupsdCheckJobs();
cupsdStopPrinter(printer, 1);
if (dtype & CUPS_PRINTER_CLASS)
- {
cupsdLogMessage(CUPSD_LOG_INFO, "Class \"%s\" stopped by \"%s\".", name,
get_username(con));
- cupsdAddEvent(CUPSD_EVENT_PRINTER_MODIFIED, printer, NULL,
- "Class \"%s\" stopped by \"%s\".", name, get_username(con));
- }
else
- {
cupsdLogMessage(CUPSD_LOG_INFO, "Printer \"%s\" stopped by \"%s\".", name,
get_username(con));
- cupsdAddEvent(CUPSD_EVENT_PRINTER_MODIFIED, printer, NULL,
- "Printer \"%s\" stopped by \"%s\".", name, get_username(con));
- }
/*
* Everything was ok, so return OK status...
}
+/*
+ * 'url_encode_attr()' - URL-encode a string attribute.
+ */
+
+static void
+url_encode_attr(ipp_attribute_t *attr, /* I - Attribute */
+ char *buffer,/* I - String buffer */
+ int bufsize)/* I - Size of buffer */
+{
+ int i; /* Looping var */
+ char *bufptr, /* Pointer into buffer */
+ *bufend, /* End of buffer */
+ *valptr; /* Pointer into value */
+
+
+ strlcpy(buffer, attr->name, bufsize);
+ bufptr = buffer + strlen(buffer);
+ bufend = buffer + bufsize - 1;
+
+ for (i = 0; i < attr->num_values; i ++)
+ {
+ if (bufptr >= bufend)
+ break;
+
+ if (i)
+ *bufptr++ = ',';
+ else
+ *bufptr++ = '=';
+
+ if (bufptr >= bufend)
+ break;
+
+ *bufptr++ = '\'';
+
+ for (valptr = attr->values[i].string.text;
+ *valptr && bufptr < bufend;
+ valptr ++)
+ if (*valptr == ' ')
+ {
+ if (bufptr >= (bufend - 2))
+ break;
+
+ *bufptr++ = '%';
+ *bufptr++ = '2';
+ *bufptr++ = '0';
+ }
+ else if (*valptr == '\'' || *valptr == '\\')
+ {
+ *bufptr++ = '\\';
+ *bufptr++ = *valptr;
+ }
+ else
+ *bufptr++ = *valptr;
+
+ if (bufptr >= bufend)
+ break;
+
+ *bufptr++ = '\'';
+ }
+
+ *bufptr = '\0';
+}
+
+
/*
* 'user_allowed()' - See if a user is allowed to print to a queue.
*/
/*
- * End of "$Id: ipp.c 5383 2006-04-07 15:36:10Z mike $".
+ * End of "$Id: ipp.c 5970 2006-09-19 20:11:08Z mike $".
*/