/*
- * "$Id: ipp.c 7014 2007-10-10 21:57:43Z mike $"
+ * "$Id: ipp.c 7682 2008-06-21 00:06:02Z mike $"
*
* IPP routines for the Common UNIX Printing System (CUPS) scheduler.
*
* add_printer() - Add a printer to the system.
* add_printer_state_reasons() - Add the "printer-state-reasons" attribute
* based upon the printer state...
- * add_queued_job_count() - Add the "queued-job-count" attribute for
+ * add_queued_job_count() - Add the "queued-job-count" attribute for the
+ * specified printer or class.
+ * apple_init_profile() - Initialize a color profile.
+ * apple_register_profiles() - Register color profiles for a printer.
+ * apple_unregister_profiles() - Remove color profiles for the specified
+ * printer.
* apply_printer_defaults() - Apply printer default options to a job.
* authenticate_job() - Set job authentication info.
* cancel_all_jobs() - Cancel all print jobs.
* cancel_job() - Cancel a print job.
* cancel_subscription() - Cancel a subscription.
* check_quotas() - Check quotas for a printer and user.
+ * check_rss_recipient() - Check that we do not have a duplicate RSS
+ * feed URI.
* copy_attribute() - Copy a single attribute.
* copy_attrs() - Copy attributes from one request to another.
* copy_banner() - Copy a banner file to the requests directory
* get_ppds() - Get the list of PPD files on the local
* system.
* get_printer_attrs() - Get printer attributes.
- * get_printers() - Get a list of printers.
+ * get_printers() - Get a list of printers or classes.
* get_subscription_attrs() - Get subscription attributes.
* get_subscriptions() - Get subscriptions.
* get_username() - Get the username associated with a request.
* move_job() - Move a job to a new destination.
* ppd_parse_line() - Parse a PPD default line.
* print_job() - Print a file to a printer or class.
- * read_ps_line() - Read a line from a PS file...
* read_ps_job_ticket() - Reads a job ticket embedded in a PS file.
* reject_jobs() - Reject print jobs to a printer.
* release_job() - Release a held print job.
+ * renew_subscription() - Renew an existing subscription...
* restart_job() - Restart an old print job.
* save_auth_info() - Save authentication information for a job.
- * save_krb5_creds() - Save Kerberos credentials for a job.
+ * save_krb5_creds() - Save Kerberos credentials for the job.
* send_document() - Send a file to a printer or class.
* send_http_error() - Send a HTTP error back to the IPP client.
* send_ipp_status() - Send a status back to the IPP client.
*/
#include "cupsd.h"
+#include <cups/ppd-private.h>
#ifdef HAVE_LIBPAPER
# include <paper.h>
#endif /* HAVE_LIBPAPER */
#ifdef __APPLE__
+# include <ApplicationServices/ApplicationServices.h>
+# include <CoreFoundation/CoreFoundation.h>
# ifdef HAVE_MEMBERSHIP_H
# include <membership.h>
# endif /* HAVE_MEMBERSHIP_H */
static void add_printer_state_reasons(cupsd_client_t *con,
cupsd_printer_t *p);
static void add_queued_job_count(cupsd_client_t *con, cupsd_printer_t *p);
+#ifdef __APPLE__
+static void apple_init_profile(ppd_file_t *ppd, cups_array_t *languages,
+ CMDeviceProfileInfo *profile, unsigned id,
+ const char *name, const char *text,
+ const char *iccfile);
+static void apple_register_profiles(cupsd_printer_t *p);
+static void apple_unregister_profiles(cupsd_printer_t *p);
+#endif /* __APPLE__ */
static void apply_printer_defaults(cupsd_printer_t *printer,
cupsd_job_t *job);
static void authenticate_job(cupsd_client_t *con, ipp_attribute_t *uri);
static void cancel_all_jobs(cupsd_client_t *con, ipp_attribute_t *uri);
static void cancel_job(cupsd_client_t *con, ipp_attribute_t *uri);
static void cancel_subscription(cupsd_client_t *con, int id);
+static int check_rss_recipient(const char *recipient);
static int check_quotas(cupsd_client_t *con, cupsd_printer_t *p);
static ipp_attribute_t *copy_attribute(ipp_t *to, ipp_attribute_t *attr,
int quickcopy);
con->http.fd, con->response->request.status.status_code,
ippErrorString(con->response->request.status.status_code));
- if (cupsdSendHeader(con, HTTP_OK, "application/ipp", AUTH_NONE))
+ if (cupsdSendHeader(con, HTTP_OK, "application/ipp", CUPSD_AUTH_NONE))
{
#ifdef CUPSD_USE_CHUNKING
/*
* Yes...
*/
- cupsdLogMessage(CUPSD_LOG_INFO, "[Job %d] Adding end banner page \"%s\".",
- job->id, attr->values[1].string.text);
+ cupsdLogJob(job, CUPSD_LOG_INFO, "Adding end banner page \"%s\".",
+ attr->values[1].string.text);
if ((kbytes = copy_banner(NULL, job, attr->values[1].string.text)) < 0)
return (-1);
if (dtype & CUPS_PRINTER_CLASS)
{
- cupsdSaveAllClasses();
+ cupsdMarkDirty(CUPSD_DIRTY_CLASSES);
cupsdLogMessage(CUPSD_LOG_INFO, "Class \"%s\" now accepting jobs (\"%s\").",
printer->name, get_username(con));
}
else
{
- cupsdSaveAllPrinters();
+ cupsdMarkDirty(CUPSD_DIRTY_PRINTERS);
cupsdLogMessage(CUPSD_LOG_INFO,
"Printer \"%s\" now accepting jobs (\"%s\").",
*/
cupsdSetPrinterAttrs(pclass);
- cupsdSaveAllClasses();
+ cupsdMarkDirty(CUPSD_DIRTY_CLASSES);
if (need_restart_job && pclass->job)
{
if (need_restart_job)
cupsdCheckJobs();
- cupsdWritePrintcap();
+ cupsdMarkDirty(CUPSD_DIRTY_PRINTCAP);
if (modify)
{
job->num_files ++;
+ job->dirty = 1;
+ cupsdMarkDirty(CUPSD_DIRTY_JOBS);
+
return (0);
}
send_http_error(con, status, printer);
return (NULL);
}
- else if ((printer->type & CUPS_PRINTER_AUTHENTICATED) &&
+ else if (printer->num_auth_info_required > 0 &&
+ strcmp(printer->auth_info_required[0], "none") &&
!con->username[0] && !auth_info)
{
send_http_error(con, HTTP_UNAUTHORIZED, printer);
}
}
+ if ((attr = ippFindAttribute(con->request, "job-sheets",
+ IPP_TAG_ZERO)) != NULL)
+ {
+ if (attr->value_tag != IPP_TAG_KEYWORD &&
+ attr->value_tag != IPP_TAG_NAME)
+ {
+ send_ipp_status(con, IPP_BAD_REQUEST, _("Bad job-sheets value type!"));
+ return (NULL);
+ }
+
+ if (attr->num_values > 2)
+ {
+ send_ipp_status(con, IPP_BAD_REQUEST,
+ _("Too many job-sheets values (%d > 2)!"),
+ attr->num_values);
+ return (NULL);
+ }
+
+ for (i = 0; i < attr->num_values; i ++)
+ if (strcmp(attr->values[i].string.text, "none") &&
+ !cupsdFindBanner(attr->values[i].string.text))
+ {
+ send_ipp_status(con, IPP_BAD_REQUEST, _("Bad job-sheets value \"%s\"!"),
+ attr->values[i].string.text);
+ return (NULL);
+ }
+ }
+
if ((attr = ippFindAttribute(con->request, "number-up",
IPP_TAG_INTEGER)) != NULL)
{
job->dtype = printer->type & (CUPS_PRINTER_CLASS | CUPS_PRINTER_IMPLICIT |
CUPS_PRINTER_REMOTE);
job->attrs = con->request;
+ job->dirty = 1;
con->request = ippNewRequest(job->attrs->request.op.operation_id);
+ cupsdMarkDirty(CUPSD_DIRTY_JOBS);
+
add_job_uuid(con, job);
apply_printer_defaults(printer, job);
cupsdSetString(&attr->values[0].string.text, Classification);
- cupsdLogMessage(CUPSD_LOG_NOTICE, "[Job %d] CLASSIFICATION FORCED "
- "job-sheets=\"%s,none\", "
- "job-originating-user-name=\"%s\"",
- job->id, Classification, job->username);
+ cupsdLogJob(job, CUPSD_LOG_NOTICE, "CLASSIFICATION FORCED "
+ "job-sheets=\"%s,none\", "
+ "job-originating-user-name=\"%s\"",
+ Classification, job->username);
}
else if (attr->num_values == 2 &&
strcmp(attr->values[0].string.text,
cupsdSetString(&attr->values[1].string.text, attr->values[0].string.text);
- cupsdLogMessage(CUPSD_LOG_NOTICE, "[Job %d] CLASSIFICATION FORCED "
- "job-sheets=\"%s,%s\", "
- "job-originating-user-name=\"%s\"",
- job->id, attr->values[0].string.text,
- attr->values[1].string.text, job->username);
+ cupsdLogJob(job, CUPSD_LOG_NOTICE, "CLASSIFICATION FORCED "
+ "job-sheets=\"%s,%s\", "
+ "job-originating-user-name=\"%s\"",
+ attr->values[0].string.text,
+ attr->values[1].string.text, job->username);
}
else if (strcmp(attr->values[0].string.text, Classification) &&
strcmp(attr->values[0].string.text, "none") &&
strcmp(attr->values[1].string.text, "none"))))
{
if (attr->num_values == 1)
- cupsdLogMessage(CUPSD_LOG_NOTICE,
- "[Job %d] CLASSIFICATION OVERRIDDEN "
- "job-sheets=\"%s\", "
- "job-originating-user-name=\"%s\"",
- job->id, attr->values[0].string.text, job->username);
+ cupsdLogJob(job, CUPSD_LOG_NOTICE,
+ "CLASSIFICATION OVERRIDDEN "
+ "job-sheets=\"%s\", "
+ "job-originating-user-name=\"%s\"",
+ attr->values[0].string.text, job->username);
else
- cupsdLogMessage(CUPSD_LOG_NOTICE,
- "[Job %d] CLASSIFICATION OVERRIDDEN "
- "job-sheets=\"%s,%s\",fffff "
- "job-originating-user-name=\"%s\"",
- job->id, attr->values[0].string.text,
- attr->values[1].string.text, job->username);
+ cupsdLogJob(job, CUPSD_LOG_NOTICE,
+ "CLASSIFICATION OVERRIDDEN "
+ "job-sheets=\"%s,%s\",fffff "
+ "job-originating-user-name=\"%s\"",
+ attr->values[0].string.text,
+ attr->values[1].string.text, job->username);
}
}
else if (strcmp(attr->values[0].string.text, Classification) &&
}
if (attr->num_values > 1)
- cupsdLogMessage(CUPSD_LOG_NOTICE,
- "[Job %d] CLASSIFICATION FORCED "
- "job-sheets=\"%s,%s\", "
- "job-originating-user-name=\"%s\"",
- job->id, attr->values[0].string.text,
- attr->values[1].string.text, job->username);
+ cupsdLogJob(job, CUPSD_LOG_NOTICE,
+ "CLASSIFICATION FORCED "
+ "job-sheets=\"%s,%s\", "
+ "job-originating-user-name=\"%s\"",
+ attr->values[0].string.text,
+ attr->values[1].string.text, job->username);
else
- cupsdLogMessage(CUPSD_LOG_NOTICE,
- "[Job %d] CLASSIFICATION FORCED "
- "job-sheets=\"%s\", "
- "job-originating-user-name=\"%s\"",
- job->id, Classification, job->username);
+ cupsdLogJob(job, CUPSD_LOG_NOTICE,
+ "CLASSIFICATION FORCED "
+ "job-sheets=\"%s\", "
+ "job-originating-user-name=\"%s\"",
+ Classification, job->username);
}
}
if (!(printer->type & (CUPS_PRINTER_REMOTE | CUPS_PRINTER_IMPLICIT)))
{
- cupsdLogMessage(CUPSD_LOG_INFO,
- "[Job %d] Adding start banner page \"%s\".",
- job->id, attr->values[0].string.text);
+ cupsdLogJob(job, CUPSD_LOG_INFO, "Adding start banner page \"%s\".",
+ attr->values[0].string.text);
if ((kbytes = copy_banner(con, job, attr->values[0].string.text)) < 0)
+ {
+ cupsdDeleteJob(job);
return (NULL);
+ }
cupsdUpdateQuota(printer, job->username, 0, kbytes);
}
{
if (!strcmp(attr->name, "notify-recipient-uri") &&
attr->value_tag == IPP_TAG_URI)
+ {
+ /*
+ * Validate the recipient scheme against the ServerBin/notifier
+ * directory...
+ */
+
+ char notifier[1024], /* Notifier filename */
+ scheme[HTTP_MAX_URI], /* Scheme portion of URI */
+ userpass[HTTP_MAX_URI], /* Username portion of URI */
+ host[HTTP_MAX_URI], /* Host portion of URI */
+ resource[HTTP_MAX_URI]; /* Resource portion of URI */
+ int port; /* Port portion of URI */
+
+
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 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 URI \"%s\" uses unknown "
+ "scheme!"), recipient);
+ ippAddInteger(con->response, IPP_TAG_SUBSCRIPTION, IPP_TAG_ENUM,
+ "notify-status-code", IPP_URI_SCHEME);
+ return;
+ }
+
+ if (!strcmp(scheme, "rss") && !check_rss_recipient(recipient))
+ {
+ send_ipp_status(con, IPP_NOT_POSSIBLE,
+ _("notify-recipient-uri URI \"%s\" is already used!"),
+ recipient);
+ ippAddInteger(con->response, IPP_TAG_SUBSCRIPTION, IPP_TAG_ENUM,
+ "notify-status-code", IPP_ATTRIBUTES);
+ 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") &&
attr = attr->next;
}
- cupsdSaveAllSubscriptions();
+ cupsdMarkDirty(CUPSD_DIRTY_SUBSCRIPTIONS);
/*
* Remove all of the subscription attributes from the job request...
strerror(errno));
return;
}
- else
- {
- cupsdLogMessage(CUPSD_LOG_DEBUG,
- "Copied interface script successfully!");
- chmod(dstfile, 0755);
- }
+
+ cupsdLogMessage(CUPSD_LOG_DEBUG,
+ "Copied interface script successfully!");
+ chmod(dstfile, 0755);
}
snprintf(dstfile, sizeof(dstfile), "%s/ppd/%s.ppd", ServerRoot,
strerror(errno));
return;
}
- else
- {
- cupsdLogMessage(CUPSD_LOG_DEBUG,
- "Copied PPD file successfully!");
- chmod(dstfile, 0644);
- }
+
+ cupsdLogMessage(CUPSD_LOG_DEBUG,
+ "Copied PPD file successfully!");
+ chmod(dstfile, 0644);
+
+#ifdef __APPLE__
+ /*
+ * (Re)register color profiles...
+ */
+
+ apple_unregister_profiles(printer);
+ apple_register_profiles(printer);
+#endif /* __APPLE__ */
}
else
{
send_ipp_status(con, IPP_INTERNAL_ERROR, _("Unable to copy PPD file!"));
return;
}
- else
- {
- cupsdLogMessage(CUPSD_LOG_DEBUG,
- "Copied PPD file successfully!");
- chmod(dstfile, 0644);
- }
+
+ cupsdLogMessage(CUPSD_LOG_DEBUG,
+ "Copied PPD file successfully!");
+ chmod(dstfile, 0644);
+
+#ifdef __APPLE__
+ /*
+ * (Re)register color profiles...
+ */
+
+ apple_unregister_profiles(printer);
+ apple_register_profiles(printer);
+#endif /* __APPLE__ */
}
}
*/
cupsdSetPrinterAttrs(printer);
- cupsdSaveAllPrinters();
+ cupsdMarkDirty(CUPSD_DIRTY_PRINTERS);
if (need_restart_job && printer->job)
{
if (need_restart_job)
cupsdCheckJobs();
- cupsdWritePrintcap();
+ cupsdMarkDirty(CUPSD_DIRTY_PRINTCAP);
if (modify)
{
}
+#ifdef __APPLE__
+/*
+ * 'apple_init_profile()' - Initialize a color profile.
+ */
+
+static void
+apple_init_profile(
+ ppd_file_t *ppd, /* I - PPD file */
+ cups_array_t *languages, /* I - Languages in the PPD file */
+ CMDeviceProfileInfo *profile, /* I - Profile record */
+ unsigned id, /* I - Profile ID */
+ const char *name, /* I - Profile name */
+ const char *text, /* I - Profile UI text */
+ const char *iccfile) /* I - ICC filename */
+{
+ char url[1024]; /* URL for profile filename */
+ CFMutableDictionaryRef dict; /* Dictionary for name */
+ char *language; /* Current language */
+ ppd_attr_t *attr; /* Profile attribute */
+ CFStringRef cflang, /* Language string */
+ cftext; /* Localized text */
+
+
+ /*
+ * Build the profile name dictionary...
+ */
+
+ dict = CFDictionaryCreateMutable(kCFAllocatorDefault, 0,
+ &kCFTypeDictionaryKeyCallBacks,
+ &kCFTypeDictionaryValueCallBacks);
+
+ cftext = CFStringCreateWithCString(kCFAllocatorDefault, text,
+ kCFStringEncodingUTF8);
+
+ if (cftext)
+ {
+ CFDictionarySetValue(dict, CFSTR("en"), cftext);
+ CFRelease(cftext);
+ }
+
+ if (languages)
+ {
+ /*
+ * Find localized names for the color profiles...
+ */
+
+ cupsArraySave(ppd->sorted_attrs);
+
+ for (language = (char *)cupsArrayFirst(languages);
+ language;
+ language = (char *)cupsArrayNext(languages))
+ {
+ if (iccfile)
+ {
+ if ((attr = _ppdLocalizedAttr(ppd, "cupsICCProfile", name,
+ language)) == NULL)
+ attr = _ppdLocalizedAttr(ppd, "APTiogaProfile", name, language);
+ }
+ else
+ attr = _ppdLocalizedAttr(ppd, "ColorModel", name, language);
+
+ if (attr && attr->text[0])
+ {
+ cflang = CFStringCreateWithCString(kCFAllocatorDefault, language,
+ kCFStringEncodingUTF8);
+ cftext = CFStringCreateWithCString(kCFAllocatorDefault, attr->text,
+ kCFStringEncodingUTF8);
+
+ if (cflang && cftext)
+ CFDictionarySetValue(dict, cflang, cftext);
+
+ if (cflang)
+ CFRelease(cflang);
+
+ if (cftext)
+ CFRelease(cftext);
+ }
+ }
+
+ cupsArrayRestore(ppd->sorted_attrs);
+ }
+
+ /*
+ * Fill in the profile data...
+ */
+
+ if (iccfile)
+ httpAssembleURI(HTTP_URI_CODING_ALL, url, sizeof(url), "file", NULL, "", 0,
+ iccfile);
+
+ profile->dataVersion = cmDeviceProfileInfoVersion1;
+ profile->profileID = id;
+ profile->profileLoc.locType = iccfile ? cmPathBasedProfile : cmNoProfileBase;
+ profile->profileName = dict;
+
+ if (iccfile)
+ strlcpy(profile->profileLoc.u.pathLoc.path, iccfile,
+ sizeof(profile->profileLoc.u.pathLoc.path));
+}
+
+
+/*
+ * 'apple_register_profiles()' - Register color profiles for a printer.
+ */
+
+static void
+apple_register_profiles(
+ cupsd_printer_t *p) /* I - Printer */
+{
+ int i; /* Looping var */
+ char ppdfile[1024], /* PPD filename */
+ iccfile[1024], /* ICC filename */
+ selector[PPD_MAX_NAME];
+ /* Profile selection string */
+ ppd_file_t *ppd; /* PPD file */
+ ppd_attr_t *attr, /* Profile attributes */
+ *profileid_attr,/* cupsProfileID attribute */
+ *q1_attr, /* ColorModel (or other) qualifier */
+ *q2_attr, /* MediaType (or other) qualifier */
+ *q3_attr; /* Resolution (or other) qualifier */
+ char q_keyword[PPD_MAX_NAME];
+ /* Qualifier keyword */
+ const char *q1_choice, /* ColorModel (or other) choice */
+ *q2_choice, /* MediaType (or other) choice */
+ *q3_choice; /* Resolution (or other) choice */
+ const char *profile_key; /* Profile keyword */
+ ppd_option_t *cm_option; /* Color model option */
+ ppd_choice_t *cm_choice; /* Color model choice */
+ int num_profiles; /* Number of profiles */
+ CMError error; /* Last error */
+ unsigned device_id, /* Printer device ID */
+ profile_id, /* Profile ID */
+ default_profile_id = 0;
+ /* Default profile ID */
+ CFMutableDictionaryRef device_name; /* Printer device name dictionary */
+ CFStringRef printer_name; /* Printer name string */
+ CMDeviceScope scope = /* Scope of the registration */
+ {
+ kCFPreferencesAnyUser,
+ kCFPreferencesCurrentHost
+ };
+ CMDeviceProfileArrayPtr profiles; /* Profiles */
+ CMDeviceProfileInfo *profile; /* Current profile */
+ cups_array_t *languages; /* Languages array */
+
+
+ /*
+ * Make sure ColorSync is available...
+ */
+
+ if (CMRegisterColorDevice == NULL)
+ return;
+
+ /*
+ * Try opening the PPD file for this printer...
+ */
+
+ snprintf(ppdfile, sizeof(ppdfile), "%s/ppd/%s.ppd", ServerRoot, p->name);
+ if ((ppd = ppdOpenFile(ppdfile)) == NULL)
+ return;
+
+ /*
+ * See if we have any profiles...
+ */
+
+ if ((attr = ppdFindAttr(ppd, "APTiogaProfile", NULL)) != NULL)
+ profile_key = "APTiogaProfile";
+ else
+ {
+ attr = ppdFindAttr(ppd, "cupsICCProfile", NULL);
+ profile_key = "cupsICCProfile";
+ }
+
+ for (num_profiles = 0; attr; attr = ppdFindNextAttr(ppd, profile_key, NULL))
+ if (attr->spec[0] && attr->value && attr->value[0])
+ {
+ if (attr->value[0] != '/')
+ snprintf(iccfile, sizeof(iccfile), "%s/profiles/%s", DataDir,
+ attr->value);
+ else
+ strlcpy(iccfile, attr->value, sizeof(iccfile));
+
+ if (access(iccfile, 0))
+ continue;
+
+ num_profiles ++;
+ }
+
+
+ /*
+ * If we have profiles, add them...
+ */
+
+ if (num_profiles > 0)
+ {
+ if (profile_key[0] == 'A')
+ {
+ /*
+ * For Tioga PPDs, get the default profile using the DefaultAPTiogaProfile
+ * attribute...
+ */
+
+ if ((attr = ppdFindAttr(ppd, "DefaultAPTiogaProfile", NULL)) != NULL &&
+ attr->value)
+ default_profile_id = atoi(attr->value);
+
+ q1_choice = q2_choice = q3_choice = NULL;
+ }
+ else
+ {
+ /*
+ * For CUPS PPDs, figure out the default profile selector values...
+ */
+
+ if ((attr = ppdFindAttr(ppd, "cupsICCQualifier1", NULL)) != NULL &&
+ attr->value && attr->value[0])
+ {
+ snprintf(q_keyword, sizeof(q_keyword), "Default%s", attr->value);
+ q1_attr = ppdFindAttr(ppd, q_keyword, NULL);
+ }
+ else if ((q1_attr = ppdFindAttr(ppd, "DefaultColorModel", NULL)) == NULL)
+ q1_attr = ppdFindAttr(ppd, "DefaultColorSpace", NULL);
+
+ if (q1_attr && q1_attr->value && q1_attr->value[0])
+ q1_choice = q1_attr->value;
+ else
+ q1_choice = "";
+
+ if ((attr = ppdFindAttr(ppd, "cupsICCQualifier2", NULL)) != NULL &&
+ attr->value && attr->value[0])
+ {
+ snprintf(q_keyword, sizeof(q_keyword), "Default%s", attr->value);
+ q2_attr = ppdFindAttr(ppd, q_keyword, NULL);
+ }
+ else
+ q2_attr = ppdFindAttr(ppd, "DefaultMediaType", NULL);
+
+ if (q2_attr && q2_attr->value && q2_attr->value[0])
+ q2_choice = q2_attr->value;
+ else
+ q2_choice = NULL;
+
+ if ((attr = ppdFindAttr(ppd, "cupsICCQualifier3", NULL)) != NULL &&
+ attr->value && attr->value[0])
+ {
+ snprintf(q_keyword, sizeof(q_keyword), "Default%s", attr->value);
+ q3_attr = ppdFindAttr(ppd, q_keyword, NULL);
+ }
+ else
+ q3_attr = ppdFindAttr(ppd, "DefaultResolution", NULL);
+
+ if (q3_attr && q3_attr->value && q3_attr->value[0])
+ q3_choice = q3_attr->value;
+ else
+ q3_choice = NULL;
+ }
+
+ /*
+ * Build the array of profiles...
+ *
+ * Note: This calloc actually requests slightly more memory than needed.
+ */
+
+ if ((profiles = calloc(num_profiles, sizeof(CMDeviceProfileArray))) == NULL)
+ {
+ cupsdLogMessage(CUPSD_LOG_ERROR,
+ "Unable to allocate memory for %d profiles!",
+ num_profiles);
+ ppdClose(ppd);
+ return;
+ }
+
+ profiles->profileCount = num_profiles;
+ languages = _ppdGetLanguages(ppd);
+
+ for (profile = profiles->profiles,
+ attr = ppdFindAttr(ppd, profile_key, NULL);
+ attr;
+ attr = ppdFindNextAttr(ppd, profile_key, NULL))
+ if (attr->spec[0] && attr->value && attr->value[0])
+ {
+ /*
+ * Add this profile...
+ */
+
+ if (attr->value[0] != '/')
+ snprintf(iccfile, sizeof(iccfile), "%s/profiles/%s", DataDir,
+ attr->value);
+ else
+ strlcpy(iccfile, attr->value, sizeof(iccfile));
+
+ if (access(iccfile, 0))
+ continue;
+
+ if (profile_key[0] == 'c')
+ {
+ cupsArraySave(ppd->sorted_attrs);
+
+ if ((profileid_attr = ppdFindAttr(ppd, "cupsProfileID",
+ attr->spec)) != NULL &&
+ profileid_attr->value && isdigit(profileid_attr->value[0] & 255))
+ profile_id = (unsigned)strtoul(profileid_attr->value, NULL, 10);
+ else
+ profile_id = _ppdHashName(attr->spec);
+
+ cupsArrayRestore(ppd->sorted_attrs);
+ }
+ else
+ profile_id = atoi(attr->spec);
+
+ apple_init_profile(ppd, languages, profile, profile_id, attr->spec,
+ attr->text[0] ? attr->text : attr->spec, iccfile);
+
+ profile ++;
+
+ /*
+ * See if this is the default profile...
+ */
+
+ if (!default_profile_id)
+ {
+ if (q2_choice)
+ {
+ if (q3_choice)
+ {
+ snprintf(selector, sizeof(selector), "%s.%s.%s",
+ q1_choice, q2_choice, q3_choice);
+ if (!strcmp(selector, attr->spec))
+ default_profile_id = profile_id;
+ }
+
+ if (!default_profile_id)
+ {
+ snprintf(selector, sizeof(selector), "%s.%s.", q1_choice,
+ q2_choice);
+ if (!strcmp(selector, attr->spec))
+ default_profile_id = profile_id;
+ }
+ }
+
+ if (!default_profile_id && q3_choice)
+ {
+ snprintf(selector, sizeof(selector), "%s..%s", q1_choice,
+ q3_choice);
+ if (!strcmp(selector, attr->spec))
+ default_profile_id = profile_id;
+ }
+
+ if (!default_profile_id)
+ {
+ snprintf(selector, sizeof(selector), "%s..", q1_choice);
+ if (!strcmp(selector, attr->spec))
+ default_profile_id = profile_id;
+ }
+ }
+ }
+
+ _ppdFreeLanguages(languages);
+ }
+ else if ((cm_option = ppdFindOption(ppd, "ColorModel")) != NULL)
+ {
+ /*
+ * Extract profiles from ColorModel option...
+ */
+
+ const char *profile_name; /* Name of generic profile */
+
+
+ num_profiles = cm_option->num_choices;
+
+ if ((profiles = calloc(num_profiles, sizeof(CMDeviceProfileArray))) == NULL)
+ {
+ cupsdLogMessage(CUPSD_LOG_ERROR,
+ "Unable to allocate memory for %d profiles!",
+ num_profiles);
+ ppdClose(ppd);
+ return;
+ }
+
+ profiles->profileCount = num_profiles;
+
+ for (profile = profiles->profiles, i = cm_option->num_choices,
+ cm_choice = cm_option->choices;
+ i > 0;
+ i --, cm_choice ++, profile ++)
+ {
+ if (!strcmp(cm_choice->choice, "Gray") ||
+ !strcmp(cm_choice->choice, "Black"))
+ profile_name = "Gray";
+ else if (!strcmp(cm_choice->choice, "RGB") ||
+ !strcmp(cm_choice->choice, "CMY"))
+ profile_name = "RGB";
+ else if (!strcmp(cm_choice->choice, "CMYK") ||
+ !strcmp(cm_choice->choice, "KCMY"))
+ profile_name = "CMYK";
+ else
+ profile_name = "DeviceN";
+
+ snprintf(selector, sizeof(selector), "%s..", profile_name);
+ profile_id = _ppdHashName(selector);
+
+ apple_init_profile(ppd, NULL, profile, profile_id, cm_choice->choice,
+ cm_choice->text, NULL);
+
+ if (cm_choice->marked)
+ default_profile_id = profile_id;
+ }
+ }
+ else
+ {
+ /*
+ * Use the default colorspace...
+ */
+
+ num_profiles = 1 + ppd->colorspace != PPD_CS_GRAY;
+
+ if ((profiles = calloc(num_profiles, sizeof(CMDeviceProfileArray))) == NULL)
+ {
+ cupsdLogMessage(CUPSD_LOG_ERROR,
+ "Unable to allocate memory for %d profiles!",
+ num_profiles);
+ ppdClose(ppd);
+ return;
+ }
+
+ profiles->profileCount = num_profiles;
+
+ apple_init_profile(ppd, NULL, profiles->profiles, _ppdHashName("Gray.."),
+ "Gray", "Gray", NULL);
+
+ switch (ppd->colorspace)
+ {
+ case PPD_CS_RGB :
+ case PPD_CS_CMY :
+ apple_init_profile(ppd, NULL, profiles->profiles + 1,
+ _ppdHashName("RGB.."), "RGB", "RGB", NULL);
+ break;
+ case PPD_CS_RGBK :
+ case PPD_CS_CMYK :
+ apple_init_profile(ppd, NULL, profiles->profiles + 1,
+ _ppdHashName("CMYK.."), "CMYK", "CMYK", NULL);
+ break;
+
+ case PPD_CS_N :
+ apple_init_profile(ppd, NULL, profiles->profiles + 1,
+ _ppdHashName("DeviceN.."), "DeviceN", "DeviceN",
+ NULL);
+ break;
+
+ default :
+ break;
+ }
+ }
+
+ if (num_profiles > 0)
+ {
+ /*
+ * Make sure we have a default profile ID...
+ */
+
+ if (!default_profile_id)
+ default_profile_id = profiles->profiles[num_profiles - 1].profileID;
+
+ /*
+ * Get the device ID hash and pathelogical name dictionary.
+ */
+
+ cupsdLogMessage(CUPSD_LOG_INFO, "Registering ICC color profiles for \"%s\"",
+ p->name);
+
+ device_id = _ppdHashName(p->name);
+ device_name = CFDictionaryCreateMutable(kCFAllocatorDefault, 0,
+ &kCFTypeDictionaryKeyCallBacks,
+ &kCFTypeDictionaryValueCallBacks);
+ printer_name = CFStringCreateWithCString(kCFAllocatorDefault, p->name,
+ kCFStringEncodingUTF8);
+
+ if (device_name && printer_name)
+ {
+ CFDictionarySetValue(device_name, CFSTR("en"), printer_name);
+
+ /*
+ * Register the device with ColorSync...
+ */
+
+ error = CMRegisterColorDevice(cmPrinterDeviceClass, device_id,
+ device_name, &scope);
+
+ /*
+ * Register the profiles...
+ */
+
+ if (error == noErr)
+ error = CMSetDeviceFactoryProfiles(cmPrinterDeviceClass, device_id,
+ default_profile_id, profiles);
+ }
+ else
+ error = 1000;
+
+ /*
+ * Clean up...
+ */
+
+ if (error != noErr)
+ cupsdLogMessage(CUPSD_LOG_ERROR,
+ "Unable to register ICC color profiles for \"%s\" - %d",
+ p->name, (int)error);
+
+ for (profile = profiles->profiles;
+ num_profiles > 0;
+ profile ++, num_profiles --)
+ CFRelease(profile->profileName);
+
+ free(profiles);
+
+ if (printer_name)
+ CFRelease(printer_name);
+
+ if (device_name)
+ CFRelease(device_name);
+ }
+
+ ppdClose(ppd);
+}
+
+
+/*
+ * 'apple_unregister_profiles()' - Remove color profiles for the specified
+ * printer.
+ */
+
+static void
+apple_unregister_profiles(
+ cupsd_printer_t *p) /* I - Printer */
+{
+ /*
+ * Make sure ColorSync is available...
+ */
+
+ if (CMUnregisterColorDevice != NULL)
+ CMUnregisterColorDevice(cmPrinterDeviceClass, _ppdHashName(p->name));
+}
+#endif /* __APPLE__ */
+
/*
* 'apply_printer_defaults()' - Apply printer default options to a job.
*/
cupsdReleaseJob(job);
- cupsdLogMessage(CUPSD_LOG_INFO, "[Job %d] Authenticated by \"%s\".", jobid,
- con->username);
+ cupsdLogJob(job, CUPSD_LOG_INFO, "Authenticated by \"%s\".", con->username);
}
if (purge)
cupsdLogMessage(CUPSD_LOG_INFO, "[Job %d] Purged by \"%s\".", jobid,
- username);
+ username);
else
cupsdLogMessage(CUPSD_LOG_INFO, "[Job %d] Canceled by \"%s\".", jobid,
- username);
+ username);
con->response->request.status.status_code = IPP_OK;
}
}
+/*
+ * 'check_rss_recipient()' - Check that we do not have a duplicate RSS feed URI.
+ */
+
+static int /* O - 1 if OK, 0 if not */
+check_rss_recipient(
+ const char *recipient) /* I - Recipient URI */
+{
+ cupsd_subscription_t *sub; /* Current subscription */
+
+
+ for (sub = (cupsd_subscription_t *)cupsArrayFirst(Subscriptions);
+ sub;
+ sub = (cupsd_subscription_t *)cupsArrayNext(Subscriptions))
+ if (sub->recipient)
+ {
+ /*
+ * Compare the URIs up to the first ?...
+ */
+
+ const char *r1, *r2;
+
+ for (r1 = recipient, r2 = sub->recipient;
+ *r1 == *r2 && *r1 && *r1 != '?' && *r2 && *r2 != '?';
+ r1 ++, r2 ++);
+
+ if (*r1 == *r2)
+ return (0);
+ }
+
+ return (1);
+}
+
+
/*
* 'check_quotas()' - Check quotas for a printer and user.
*/
*/
#ifdef HAVE_MBR_UID_TO_UUID
- if ((mbr_err = mbr_group_name_to_uuid((char *)p->users[i] + 1,
- grp_uuid)) != 0)
+ if (p->users[i][1] == '#')
+ {
+ if (uuid_parse((char *)p->users[i] + 2, grp_uuid))
+ uuid_clear(grp_uuid);
+ }
+ else if ((mbr_err = mbr_group_name_to_uuid((char *)p->users[i] + 1,
+ grp_uuid)) != 0)
{
/*
* Invalid ACL entries are ignored for matching; just record a
"Access control entry \"%s\" not a valid group name; "
"entry ignored", p->users[i]);
}
- else
- {
- if ((mbr_err = mbr_check_membership(usr_uuid, grp_uuid,
- &is_member)) != 0)
- {
- /*
- * At this point, there should be no errors, but check anyways...
- */
- cupsdLogMessage(CUPSD_LOG_DEBUG,
- "check_quotas: group \"%s\" membership check "
- "failed (err=%d)", p->users[i] + 1, mbr_err);
- is_member = 0;
- }
-
- /*
- * Stop if we found a match...
+ if ((mbr_err = mbr_check_membership(usr_uuid, grp_uuid,
+ &is_member)) != 0)
+ {
+ /*
+ * At this point, there should be no errors, but check anyways...
*/
- if (is_member)
- break;
+ cupsdLogMessage(CUPSD_LOG_DEBUG,
+ "check_quotas: group \"%s\" membership check "
+ "failed (err=%d)", p->users[i] + 1, mbr_err);
+ is_member = 0;
}
+
+ /*
+ * Stop if we found a match...
+ */
+
+ if (is_member)
+ break;
+
#else
if (cupsdCheckGroup(username, pw, p->users[i] + 1))
break;
#ifdef HAVE_MBR_UID_TO_UUID
else
{
- if ((mbr_err = mbr_user_name_to_uuid((char *)p->users[i],
- usr2_uuid)) != 0)
+ if (p->users[i][0] == '#')
+ {
+ if (uuid_parse((char *)p->users[i] + 1, usr2_uuid))
+ uuid_clear(usr2_uuid);
+ }
+ else if ((mbr_err = mbr_user_name_to_uuid((char *)p->users[i],
+ usr2_uuid)) != 0)
{
/*
* Invalid ACL entries are ignored for matching; just record a
"Access control entry \"%s\" not a valid user name; "
"entry ignored", p->users[i]);
}
- else
- {
- if ((mbr_err = mbr_check_membership(usr_uuid, usr2_uuid,
- &is_member)) != 0)
- {
- cupsdLogMessage(CUPSD_LOG_DEBUG,
- "check_quotas: User \"%s\" identity check failed "
- "(err=%d)", p->users[i], mbr_err);
- is_member = 0;
- }
- if (is_member)
- break;
+ if ((mbr_err = mbr_check_membership(usr_uuid, usr2_uuid,
+ &is_member)) != 0)
+ {
+ cupsdLogMessage(CUPSD_LOG_DEBUG,
+ "check_quotas: User \"%s\" identity check failed "
+ "(err=%d)", p->users[i], mbr_err);
+ is_member = 0;
}
+
+ if (is_member)
+ break;
}
#else
else if (!strcasecmp(username, p->users[i]))
ipp_attribute_t *attr; /* Attribute */
- cupsdLogMessage(CUPSD_LOG_DEBUG2, "copy_banner(%p[%d], %p[%d], %s)",
+ cupsdLogMessage(CUPSD_LOG_DEBUG2,
+ "copy_banner(con=%p[%d], job=%p[%d], name=\"%s\")",
con, con ? con->http.fd : -1, job, job->id,
name ? name : "(null)");
if ((out = cupsFileOpen(filename, "w")) == NULL)
{
cupsdLogMessage(CUPSD_LOG_ERROR,
- "copy_banner: Unable to create banner job file %s - %s",
+ "Unable to create banner job file %s - %s",
filename, strerror(errno));
job->num_files --;
return (0);
cupsFileClose(out);
unlink(filename);
cupsdLogMessage(CUPSD_LOG_ERROR,
- "copy_banner: Unable to open banner template file %s - %s",
+ "Unable to open banner template file %s - %s",
filename, strerror(errno));
job->num_files --;
return (0);
printer->recoverable);
#endif /* __APPLE__ */
+ if (!ra || cupsArrayFind(ra, "marker-change-time"))
+ ippAddInteger(con->response, IPP_TAG_PRINTER, IPP_TAG_INTEGER,
+ "marker-change-time", printer->marker_time);
+
+ if (printer->num_printers > 0 &&
+ (!ra || cupsArrayFind(ra, "member-uris")))
+ {
+ ipp_attribute_t *member_uris; /* member-uris attribute */
+ cupsd_printer_t *p2; /* Printer in class */
+ ipp_attribute_t *p2_uri; /* printer-uri-supported for class printer */
+
+
+ if ((member_uris = ippAddStrings(con->response, IPP_TAG_PRINTER,
+ IPP_TAG_URI, "member-uris",
+ printer->num_printers, NULL,
+ NULL)) != NULL)
+ {
+ for (i = 0; i < printer->num_printers; i ++)
+ {
+ p2 = printer->printers[i];
+
+ if ((p2_uri = ippFindAttribute(p2->attrs, "printer-uri-supported",
+ IPP_TAG_URI)) != NULL)
+ member_uris->values[i].string.text =
+ _cupsStrAlloc(p2_uri->values[0].string.text);
+ else
+ {
+ httpAssembleURIf(HTTP_URI_CODING_ALL, printer_uri,
+ sizeof(printer_uri), "ipp", NULL, con->servername,
+ con->serverport,
+ (p2->type & CUPS_PRINTER_CLASS) ?
+ "/classes/%s" : "/printers/%s", p2->name);
+ member_uris->values[i].string.text = _cupsStrAlloc(printer_uri);
+ }
+ }
+ }
+ }
+
if (printer->alert && (!ra || cupsArrayFind(ra, "printer-alert")))
ippAddString(con->response, IPP_TAG_PRINTER, IPP_TAG_STRING,
"printer-alert", NULL, printer->alert);
ippAddDate(con->response, IPP_TAG_PRINTER, "printer-current-time",
ippTimeToDate(curtime));
+#ifdef HAVE_DNSSD
+ if (!ra || cupsArrayFind(ra, "printer-dns-sd-name"))
+ {
+ if (printer->reg_name)
+ ippAddString(con->response, IPP_TAG_PRINTER, IPP_TAG_NAME,
+ "printer-dns-sd-name", NULL, printer->reg_name);
+ else
+ ippAddInteger(con->response, IPP_TAG_PRINTER, IPP_TAG_NOVALUE,
+ "printer-dns-sd-name", 0);
+ }
+#endif /* HAVE_DNSSD */
+
if (!ra || cupsArrayFind(ra, "printer-error-policy"))
ippAddString(con->response, IPP_TAG_PRINTER, IPP_TAG_NAME,
"printer-error-policy", NULL, printer->error_policy);
* Save and log the job...
*/
- cupsdSaveJob(job);
-
- cupsdLogMessage(CUPSD_LOG_INFO, "[Job %d] Queued on \"%s\" by \"%s\".",
- job->id, job->dest, job->username);
+ cupsdLogJob(job, CUPSD_LOG_INFO, "Queued on \"%s\" by \"%s\".",
+ job->dest, job->username);
}
cupsArrayAdd(ra, "pdl-override-supported");
cupsArrayAdd(ra, "printer-alert");
cupsArrayAdd(ra, "printer-alert-description");
+ cupsArrayAdd(ra, "printer-commands");
cupsArrayAdd(ra, "printer-current-time");
cupsArrayAdd(ra, "printer-driver-installer");
+ cupsArrayAdd(ra, "printer-dns-sd-name");
cupsArrayAdd(ra, "printer-info");
cupsArrayAdd(ra, "printer-is-accepting-jobs");
cupsArrayAdd(ra, "printer-location");
cupsArrayAdd(ra, "printer-state");
cupsArrayAdd(ra, "printer-state-message");
cupsArrayAdd(ra, "printer-state-reasons");
+ cupsArrayAdd(ra, "printer-type");
cupsArrayAdd(ra, "printer-up-time");
cupsArrayAdd(ra, "printer-uri-supported");
cupsArrayAdd(ra, "queued-job-count");
for (attr = con->request->attrs; attr; attr = attr->next)
{
if (attr->group_tag != IPP_TAG_ZERO)
- cupsdLogMessage(CUPSD_LOG_DEBUG, "g%04x v%04x %s", attr->group_tag,
+ cupsdLogMessage(CUPSD_LOG_DEBUG2, "g%04x v%04x %s", attr->group_tag,
attr->value_tag, attr->name);
else
- cupsdLogMessage(CUPSD_LOG_DEBUG, "----SEP----");
+ cupsdLogMessage(CUPSD_LOG_DEBUG2, "----SEP----");
}
#endif /* DEBUG */
"notify-status-code", IPP_URI_SCHEME);
return;
}
+
+ if (!strcmp(scheme, "rss") && !check_rss_recipient(recipient))
+ {
+ send_ipp_status(con, IPP_NOT_POSSIBLE,
+ _("notify-recipient-uri URI \"%s\" is already used!"),
+ recipient);
+ ippAddInteger(con->response, IPP_TAG_SUBSCRIPTION, IPP_TAG_ENUM,
+ "notify-status-code", IPP_ATTRIBUTES);
+ return;
+ }
}
else if (!strcmp(attr->name, "notify-pull-method") &&
attr->value_tag == IPP_TAG_KEYWORD)
attr = attr->next;
}
- cupsdSaveAllSubscriptions();
-
+ cupsdMarkDirty(CUPSD_DIRTY_SUBSCRIPTIONS);
}
printer->name);
unlink(filename);
+#ifdef __APPLE__
+ /*
+ * Unregister color profiles...
+ */
+
+ apple_unregister_profiles(printer);
+#endif /* __APPLE__ */
+
if (dtype & CUPS_PRINTER_CLASS)
{
cupsdLogMessage(CUPSD_LOG_INFO, "Class \"%s\" deleted by \"%s\".",
printer->name, get_username(con));
cupsdDeletePrinter(printer, 0);
- cupsdSaveAllClasses();
+ cupsdMarkDirty(CUPSD_DIRTY_CLASSES);
}
else
{
printer->name, get_username(con));
cupsdDeletePrinter(printer, 0);
- cupsdSaveAllPrinters();
+ cupsdMarkDirty(CUPSD_DIRTY_PRINTERS);
}
- cupsdWritePrintcap();
+ cupsdMarkDirty(CUPSD_DIRTY_PRINTCAP);
/*
* Return with no errors...
get_devices(cupsd_client_t *con) /* I - Client connection */
{
http_status_t status; /* Policy status */
- ipp_attribute_t *limit, /* Limit attribute */
- *requested; /* requested-attributes attribute */
+ ipp_attribute_t *limit, /* limit attribute */
+ *timeout, /* timeout attribute */
+ *requested, /* requested-attributes attribute */
+ *exclude; /* exclude-schemes attribute */
char command[1024], /* cups-deviced command */
options[1024], /* Options to pass to command */
- requested_str[256];
+ requested_str[256],
/* String for requested attributes */
+ exclude_str[512];
+ /* String for excluded attributes */
cupsdLogMessage(CUPSD_LOG_DEBUG2, "get_devices(%p[%d])", con, con->http.fd);
* Run cups-deviced command with the given options...
*/
- limit = ippFindAttribute(con->request, "limit", IPP_TAG_INTEGER);
+ limit = ippFindAttribute(con->request, "limit", IPP_TAG_INTEGER);
+ timeout = ippFindAttribute(con->request, "timeout", IPP_TAG_INTEGER);
requested = ippFindAttribute(con->request, "requested-attributes",
IPP_TAG_KEYWORD);
+ exclude = ippFindAttribute(con->request, "exclude-schemes", IPP_TAG_NAME);
if (requested)
url_encode_attr(requested, requested_str, sizeof(requested_str));
else
strlcpy(requested_str, "requested-attributes=all", sizeof(requested_str));
+ if (exclude)
+ url_encode_attr(exclude, exclude_str, sizeof(exclude_str));
+ else
+ exclude_str[0] = '\0';
+
snprintf(command, sizeof(command), "%s/daemon/cups-deviced", ServerBin);
snprintf(options, sizeof(options),
- "%d+%d+%d+%s",
+ "%d+%d+%d+%d+%s%s%s",
con->request->request.op.request_id,
- limit ? limit->values[0].integer : 0, (int)User,
- requested_str);
+ limit ? limit->values[0].integer : 0,
+ timeout ? timeout->values[0].integer : 10,
+ (int)User,
+ requested_str,
+ exclude_str[0] ? "%20" : "", exclude_str);
if (cupsdSendCommand(con, command, options, 1))
{
completed = 0;
list = Jobs;
}
+ else if (attr && !strcmp(attr->values[0].string.text, "printing"))
+ {
+ completed = 0;
+ list = PrintingJobs;
+ }
else
{
completed = 0;
IPP_TAG_INTEGER)) != NULL)
limit = attr->values[0].integer;
else
- limit = 1000000;
+ limit = 0;
if ((attr = ippFindAttribute(con->request, "first-job-id",
IPP_TAG_INTEGER)) != NULL)
*/
for (count = 0, job = (cupsd_job_t *)cupsArrayFirst(list);
- count < limit && job;
+ (limit <= 0 || count < limit) && job;
job = (cupsd_job_t *)cupsArrayNext(list))
{
/*
* access...
*/
- if (printer->num_users && username && !user_allowed(printer, username))
+ if (!(printer->type & CUPS_PRINTER_AUTHENTICATED) &&
+ printer->num_users && username && !user_allowed(printer, username))
continue;
/*
cupsdHoldJob(job);
- cupsdAddEvent(CUPSD_EVENT_JOB_STATE, job->printer, job,
+ cupsdAddEvent(CUPSD_EVENT_JOB_STATE, cupsdFindDest(job->dest), job,
"Job held by user.");
if ((newattr = ippFindAttribute(con->request, "job-hold-until",
cupsdSetJobHoldUntil(job, attr->values[0].string.text);
- cupsdAddEvent(CUPSD_EVENT_JOB_CONFIG_CHANGED, job->printer, job,
+ cupsdAddEvent(CUPSD_EVENT_JOB_CONFIG_CHANGED, cupsdFindDest(job->dest), job,
"Job job-hold-until value changed by user.");
}
- cupsdLogMessage(CUPSD_LOG_INFO, "[Job %d] Held by \"%s\".", jobid,
- username);
+ cupsdLogJob(job, CUPSD_LOG_INFO, "Held by \"%s\".", username);
con->response->request.status.status_code = IPP_OK;
}
return;
}
- /*
- * Check policy...
- */
-
- if ((status = cupsdCheckPolicy(dprinter->op_policy_ptr, con,
- NULL)) != HTTP_OK)
- {
- send_http_error(con, status, dprinter);
- return;
- }
-
/*
* See if we have a job URI or a printer URI...
*/
}
}
+ /*
+ * Check the policy of the destination printer...
+ */
+
+ if ((status = cupsdCheckPolicy(dprinter->op_policy_ptr, con,
+ job ? job->username : NULL)) != HTTP_OK)
+ {
+ send_http_error(con, status, dprinter);
+ return;
+ }
+
/*
* Now move the job or jobs...
*/
ipp_attribute_t *doc_name; /* document-name attribute */
- cupsdLogMessage(CUPSD_LOG_DEBUG, "print_job: auto-typing file...");
+ cupsdLogMessage(CUPSD_LOG_DEBUG, "[Job ???] Auto-typing file...");
doc_name = ippFindAttribute(con->request, "document-name", IPP_TAG_NAME);
filetype = mimeFileType(MimeDatabase, con->filename,
if (!filetype)
filetype = mimeType(MimeDatabase, super, type);
+
+ cupsdLogMessage(CUPSD_LOG_INFO, "[Job ???] Request file type is %s/%s.",
+ filetype->super, filetype->type);
}
else
filetype = mimeType(MimeDatabase, super, type);
if ((job = add_job(con, printer, filetype)) == NULL)
return;
- cupsdLogMessage(CUPSD_LOG_INFO, "[Job %d] Adding job file of type %s/%s.",
- job->id, filetype->super, filetype->type);
-
/*
* Update quota data...
*/
* Log and save the job...
*/
- cupsdLogMessage(CUPSD_LOG_INFO, "[Job %d] Queued on \"%s\" by \"%s\".",
- job->id, job->dest, job->username);
- cupsdLogMessage(CUPSD_LOG_DEBUG, "[Job %d] hold_until = %d", job->id,
- (int)job->hold_until);
-
- cupsdSaveJob(job);
+ cupsdLogJob(job, CUPSD_LOG_INFO,
+ "File of type %s/%s queued by \"%s\".",
+ filetype->super, filetype->type, job->username);
+ cupsdLogJob(job, CUPSD_LOG_DEBUG, "hold_until=%d", (int)job->hold_until);
/*
* Start the job if possible...
if (dtype & CUPS_PRINTER_CLASS)
{
- cupsdSaveAllClasses();
+ cupsdMarkDirty(CUPSD_DIRTY_CLASSES);
cupsdLogMessage(CUPSD_LOG_INFO, "Class \"%s\" rejecting jobs (\"%s\").",
printer->name, get_username(con));
}
else
{
- cupsdSaveAllPrinters();
+ cupsdMarkDirty(CUPSD_DIRTY_PRINTERS);
cupsdLogMessage(CUPSD_LOG_INFO, "Printer \"%s\" rejecting jobs (\"%s\").",
printer->name, get_username(con));
attr->value_tag = IPP_TAG_KEYWORD;
attr->values[0].string.text = _cupsStrAlloc("no-hold");
- cupsdAddEvent(CUPSD_EVENT_JOB_CONFIG_CHANGED, job->printer, job,
+ cupsdAddEvent(CUPSD_EVENT_JOB_CONFIG_CHANGED, cupsdFindDest(job->dest), job,
"Job job-hold-until value changed by user.");
}
cupsdReleaseJob(job);
- cupsdAddEvent(CUPSD_EVENT_JOB_STATE, job->printer, job,
+ cupsdAddEvent(CUPSD_EVENT_JOB_STATE, cupsdFindDest(job->dest), job,
"Job released by user.");
- cupsdLogMessage(CUPSD_LOG_INFO, "[Job %d] Released by \"%s\".", jobid,
- username);
+ cupsdLogJob(job, CUPSD_LOG_INFO, "Released by \"%s\".", username);
con->response->request.status.status_code = IPP_OK;
}
sub->expire = sub->lease ? time(NULL) + sub->lease : 0;
- cupsdSaveAllSubscriptions();
+ cupsdMarkDirty(CUPSD_DIRTY_SUBSCRIPTIONS);
con->response->request.status.status_code = IPP_OK;
cupsdRestartJob(job);
- cupsdLogMessage(CUPSD_LOG_INFO, "[Job %d] Restarted by \"%s\".", jobid,
- username);
+ cupsdLogJob(job, CUPSD_LOG_INFO, "Restarted by \"%s\".", username);
con->response->request.status.status_code = IPP_OK;
}
cupsdSetStringf(&(job->ccname), "KRB5CCNAME=FILE:%s",
krb5_cc_get_name(KerberosContext, job->ccache));
- cupsdLogMessage(CUPSD_LOG_DEBUG2, "[Job %d] save_krb5_creds: %s", job->id,
- job->ccname);
+ cupsdLogJob(job, CUPSD_LOG_DEBUG2, "save_krb5_creds: %s", job->ccname);
# endif /* HAVE_KRB5_CC_NEW_UNIQUE || HAVE_HEIMDAL */
}
#endif /* HAVE_GSSAPI && HAVE_KRB5_H */
ipp_attribute_t *uri) /* I - Printer URI */
{
ipp_attribute_t *attr; /* Current attribute */
- ipp_attribute_t *format; /* Document-format attribute */
+ ipp_attribute_t *format; /* Request's document-format attribute */
+ ipp_attribute_t *jformat; /* Job's document-format attribute */
const char *default_format;/* document-format-default value */
int jobid; /* Job ID number */
cupsd_job_t *job; /* Current job */
struct stat fileinfo; /* File information */
int kbytes; /* Size of file */
int compression; /* Type of compression */
+ int start_job; /* Start the job? */
cupsdLogMessage(CUPSD_LOG_DEBUG2, "send_document(%p[%d], %s)", con,
ipp_attribute_t *doc_name; /* document-name attribute */
- cupsdLogMessage(CUPSD_LOG_DEBUG, "send_document: auto-typing file...");
+ cupsdLogJob(job, CUPSD_LOG_DEBUG, "Auto-typing file...");
doc_name = ippFindAttribute(con->request, "document-name", IPP_TAG_NAME);
filetype = mimeFileType(MimeDatabase, con->filename,
if (!filetype)
filetype = mimeType(MimeDatabase, super, type);
+
+ cupsdLogJob(job, CUPSD_LOG_DEBUG, "Request file type is %s/%s.",
+ filetype->super, filetype->type);
}
else
filetype = mimeType(MimeDatabase, super, type);
+ jformat = ippFindAttribute(job->attrs, "document-format", IPP_TAG_MIMETYPE);
+
if (filetype &&
- (!format ||
+ (!jformat ||
(!strcmp(super, "application") && !strcmp(type, "octet-stream"))))
{
/*
snprintf(mimetype, sizeof(mimetype), "%s/%s", filetype->super,
filetype->type);
- if (format)
+ if (jformat)
{
- _cupsStrFree(format->values[0].string.text);
+ _cupsStrFree(jformat->values[0].string.text);
- format->values[0].string.text = _cupsStrAlloc(mimetype);
+ jformat->values[0].string.text = _cupsStrAlloc(mimetype);
}
else
- ippAddString(con->request, IPP_TAG_JOB, IPP_TAG_MIMETYPE,
+ ippAddString(job->attrs, IPP_TAG_JOB, IPP_TAG_MIMETYPE,
"document-format", NULL, mimetype);
}
else if (!filetype)
return;
}
- cupsdLogMessage(CUPSD_LOG_DEBUG,
- "send_document: request file type is %s/%s.",
- filetype->super, filetype->type);
-
/*
* Add the file to the job...
*/
cupsdClearString(&con->filename);
- cupsdLogMessage(CUPSD_LOG_INFO,
- "File of type %s/%s queued in job #%d by \"%s\".",
- filetype->super, filetype->type, job->id, job->username);
+ cupsdLogJob(job, CUPSD_LOG_INFO, "File of type %s/%s queued by \"%s\".",
+ filetype->super, filetype->type, job->username);
/*
* Start the job if this is the last document...
}
}
- cupsdSaveJob(job);
+ job->dirty = 1;
+ cupsdMarkDirty(CUPSD_DIRTY_JOBS);
- /*
- * Start the job if possible... Since cupsdCheckJobs() can cancel a
- * job if it doesn't print, we need to re-find the job afterwards...
- */
-
- jobid = job->id;
-
- cupsdCheckJobs();
-
- job = cupsdFindJob(jobid);
+ start_job = 1;
}
else
{
job->state->values[0].integer = IPP_JOB_HELD;
job->state_value = IPP_JOB_HELD;
job->hold_until = time(NULL) + 60;
- cupsdSaveJob(job);
+ job->dirty = 1;
+
+ cupsdMarkDirty(CUPSD_DIRTY_JOBS);
}
+
+ start_job = 0;
}
/*
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_CANCELED);
+ job->state_value);
add_job_state_reasons(con, job);
con->response->request.status.status_code = IPP_OK;
+
+ /*
+ * Start the job if necessary...
+ */
+
+ if (start_job)
+ cupsdCheckJobs();
}
if (status == HTTP_UNAUTHORIZED &&
printer && printer->num_auth_info_required > 0 &&
!strcmp(printer->auth_info_required[0], "negotiate"))
- cupsdSendError(con, status, AUTH_NEGOTIATE);
+ cupsdSendError(con, status, CUPSD_AUTH_NEGOTIATE);
else if (printer)
{
char resource[HTTP_MAX_URI]; /* Resource portion of URI */
cupsd_location_t *auth; /* Pointer to authentication element */
+ int auth_type; /* Type of authentication required */
if (printer->type & CUPS_PRINTER_CLASS)
snprintf(resource, sizeof(resource), "/printers/%s", printer->name);
if ((auth = cupsdFindBest(resource, HTTP_POST)) == NULL ||
- auth->type == AUTH_NONE)
- auth = cupsdFindPolicyOp(printer->op_policy_ptr, IPP_PRINT_JOB);
+ auth->type == CUPSD_AUTH_NONE)
+ auth = cupsdFindPolicyOp(printer->op_policy_ptr,
+ con->request ?
+ con->request->request.op.operation_id :
+ IPP_PRINT_JOB);
+
+ if (!auth)
+ auth_type = CUPSD_AUTH_NONE;
+ else if (auth->type == CUPSD_AUTH_DEFAULT)
+ auth_type = DefaultAuthType;
+ else
+ auth_type = auth->type;
- cupsdSendError(con, status, auth ? auth->type : AUTH_NONE);
+ cupsdSendError(con, status, auth_type);
}
else
- cupsdSendError(con, status, AUTH_NONE);
+ cupsdSendError(con, status, CUPSD_AUTH_NONE);
ippDelete(con->response);
con->response = NULL;
{
http_status_t status; /* Policy status */
cups_ptype_t dtype; /* Destination type (printer/class) */
- cupsd_printer_t *printer; /* Printer */
+ cupsd_printer_t *printer, /* Printer */
+ *oldprinter; /* Old default printer */
cupsdLogMessage(CUPSD_LOG_DEBUG2, "set_default(%p[%d], %s)", con,
* Set it as the default...
*/
+ oldprinter = DefaultPrinter;
DefaultPrinter = printer;
- cupsdSaveAllPrinters();
- cupsdSaveAllClasses();
+ if (oldprinter)
+ cupsdAddEvent(CUPSD_EVENT_PRINTER_STATE, oldprinter, NULL,
+ "%s is no longer the default printer.", oldprinter->name);
- cupsdWritePrintcap();
+ cupsdAddEvent(CUPSD_EVENT_PRINTER_STATE, printer, NULL,
+ "%s is now the default printer.", printer->name);
+
+ cupsdMarkDirty(CUPSD_DIRTY_PRINTERS | CUPSD_DIRTY_CLASSES |
+ CUPSD_DIRTY_REMOTE | CUPSD_DIRTY_PRINTCAP);
cupsdLogMessage(CUPSD_LOG_INFO,
"Default destination set to \"%s\" by \"%s\".",
else if (con->response->request.status.status_code == IPP_OK)
{
cupsdSetJobPriority(job, attr->values[0].integer);
- event |= CUPSD_EVENT_JOB_CONFIG_CHANGED;
+ event |= CUPSD_EVENT_JOB_CONFIG_CHANGED |
+ CUPSD_EVENT_PRINTER_QUEUE_ORDER_CHANGED;
}
}
else if (!strcmp(attr->name, "job-state"))
* Save the job...
*/
- cupsdSaveJob(job);
+ job->dirty = 1;
+ cupsdMarkDirty(CUPSD_DIRTY_JOBS);
/*
* Send events as needed...
*/
+ if (event & CUPSD_EVENT_PRINTER_QUEUE_ORDER_CHANGED)
+ cupsdAddEvent(CUPSD_EVENT_PRINTER_QUEUE_ORDER_CHANGED,
+ cupsdFindDest(job->dest), job,
+ "Job priority changed by user.");
+
if (event & CUPSD_EVENT_JOB_STATE)
- cupsdAddEvent(CUPSD_EVENT_JOB_STATE, job->printer, job,
+ cupsdAddEvent(CUPSD_EVENT_JOB_STATE, cupsdFindDest(job->dest), 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,
+ cupsdAddEvent(CUPSD_EVENT_JOB_CONFIG_CHANGED, cupsdFindDest(job->dest), job,
"Job options changed by user.");
/*
{
int i; /* Looping var */
struct passwd *pw; /* User password data */
+ char baseuser[256], /* Base username */
+ *baseptr; /* Pointer to "@" in base username */
if (p->num_users == 0)
if (!strcmp(username, "root"))
return (1);
+ if (strchr(username, '@'))
+ {
+ /*
+ * Strip @REALM for username check...
+ */
+
+ strlcpy(baseuser, username, sizeof(baseuser));
+
+ if ((baseptr = strchr(baseuser, '@')) != NULL)
+ *baseptr = '\0';
+
+ username = baseuser;
+ }
+
pw = getpwnam(username);
endpwent();
if (cupsdCheckGroup(username, pw, p->users[i] + 1))
break;
}
+ else if (p->users[i][0] == '#')
+ {
+ /*
+ * Check UUID...
+ */
+
+ if (cupsdCheckGroup(username, pw, p->users[i]))
+ break;
+ }
else if (!strcasecmp(username, p->users[i]))
break;
}
/*
- * End of "$Id: ipp.c 7014 2007-10-10 21:57:43Z mike $".
+ * End of "$Id: ipp.c 7682 2008-06-21 00:06:02Z mike $".
*/