cupsdSetString(&p->info, name);
cupsdSetString(&p->hostname, ServerName);
- cupsdSetStringf(&p->uri, "ipp://%s:%d/printers/%s", ServerName, LocalPort, name);
- cupsdSetDeviceURI(p, "file:/dev/null");
+ cupsdSetStringf(&p->uri, "ipp://%s:%d/printers/%s", ServerName, RemotePort,
+ name);
+ cupsdSetDeviceURI(p, "file:///dev/null");
p->state = IPP_PRINTER_STOPPED;
p->state_time = time(NULL);
#endif /* __APPLE__ */
if (p->num_reasons == 0)
ippAddString(history, IPP_TAG_PRINTER, IPP_TAG_KEYWORD,
- "printer-state-reasons", NULL,
- p->state == IPP_PRINTER_STOPPED ? "paused" : "none");
+ "printer-state-reasons", NULL, "none");
else
ippAddStrings(history, IPP_TAG_PRINTER, IPP_TAG_KEYWORD,
"printer-state-reasons", p->num_reasons, NULL,
"separate-documents-uncollated-copies",
"separate-documents-collated-copies"
};
- static const char * const errors[] = /* printer-error-policy-supported values */
- {
- "abort-job",
- "retry-current-job",
- "retry-job",
- "stop-printer"
- };
static const char * const notify_attrs[] =
{ /* notify-attributes-supported values */
"printer-state-change-time",
ippAddString(CommonData, IPP_TAG_PRINTER, IPP_TAG_KEYWORD | IPP_TAG_COPY,
"pdl-override-supported", NULL, "not-attempted");
- /* printer-error-policy-supported */
- ippAddStrings(CommonData, IPP_TAG_PRINTER, IPP_TAG_NAME | IPP_TAG_COPY,
- "printer-error-policy-supported",
- sizeof(errors) / sizeof(errors[0]), NULL, errors);
-
/* printer-op-policy-supported */
attr = ippAddStrings(CommonData, IPP_TAG_PRINTER, IPP_TAG_NAME | IPP_TAG_COPY,
"printer-op-policy-supported", cupsArrayCount(Policies),
* Stop printing on this printer...
*/
- cupsdStopPrinter(p, update);
+ cupsdSetPrinterState(p, IPP_PRINTER_STOPPED, update);
+
+ if (p->job)
+ cupsdSetJobState(p->job, IPP_JOB_PENDING, CUPSD_JOB_FORCE,
+ update ? "Job stopped due to printer being deleted." :
+ "Job stopped.");
/*
* If this printer is the next for browsing, point to the next one...
free(p->history);
}
+ delete_printer_filters(p);
+
for (i = 0; i < p->num_reasons; i ++)
_cupsStrFree(p->reasons[i]);
ippDelete(p->attrs);
ippDelete(p->ppd_attrs);
- delete_printer_filters(p);
-
mimeDeleteType(MimeDatabase, p->filetype);
mimeDeleteType(MimeDatabase, p->prefiltertype);
void
cupsdLoadAllPrinters(void)
{
+ int i; /* Looping var */
cups_file_t *fp; /* printers.conf file */
int linenum; /* Current line number */
char line[4096], /* Line from file */
else if (!strcasecmp(line, "Reason"))
{
if (value &&
- p->num_reasons < (int)(sizeof(p->reasons) / sizeof(p->reasons[0])))
+ strcmp(value, "com.apple.print.recoverable-warning") &&
+ strcmp(value, "connecting-to-device") &&
+ strcmp(value, "cups-insecure-filter-warning") &&
+ strcmp(value, "cups-missing-filter-warning"))
{
- p->reasons[p->num_reasons] = _cupsStrAlloc(value);
- p->num_reasons ++;
+ for (i = 0 ; i < p->num_reasons; i ++)
+ if (!strcmp(value, p->reasons[i]))
+ break;
+
+ if (i >= p->num_reasons &&
+ p->num_reasons < (int)(sizeof(p->reasons) / sizeof(p->reasons[0])))
+ {
+ p->reasons[p->num_reasons] = _cupsStrAlloc(value);
+ p->num_reasons ++;
+ }
}
else
cupsdLogMessage(CUPSD_LOG_ERROR,
if (value && !strcasecmp(value, "idle"))
p->state = IPP_PRINTER_IDLE;
else if (value && !strcasecmp(value, "stopped"))
+ {
p->state = IPP_PRINTER_STOPPED;
+ cupsdSetPrinterReasons(p, "+paused");
+ }
else
cupsdLogMessage(CUPSD_LOG_ERROR,
"Syntax error on line %d of printers.conf.", linenum);
cupsFilePrintf(fp, "StateTime %d\n", (int)printer->state_time);
for (i = 0; i < printer->num_reasons; i ++)
- if (strcmp(printer->reasons[i], "connecting-to-device"))
+ if (strcmp(printer->reasons[i], "com.apple.print.recoverable-warning") &&
+ strcmp(printer->reasons[i], "connecting-to-device") &&
+ strcmp(printer->reasons[i], "cups-insecure-filter-warning") &&
+ strcmp(printer->reasons[i], "cups-missing-filter-warning"))
cupsFilePutConf(fp, "Reason", printer->reasons[i]);
cupsFilePrintf(fp, "Type %d\n", printer->type);
* Don't allow empty values...
*/
- if (!*value)
+ if (!*value && strcmp(name, "marker-message"))
{
cupsdLogMessage(CUPSD_LOG_ERROR, "Ignoring empty \"%s\" attribute", name);
return;
ipp_attribute_t *attr; /* Attribute data */
cups_option_t *option; /* Current printer option */
char *filter; /* Current filter */
+ static const char * const air_none[] =
+ { /* No authentication */
+ "none"
+ };
static const char * const air_userpass[] =
{ /* Basic/Digest authentication */
"username",
"password"
};
-#ifdef HAVE_GSSAPI
- static const char * const air_negotiate[] =
- { /* Kerberos authentication */
- "negotiate"
- };
-#endif /* HAVE_GSSAPI */
- static const char * const air_none[] =
- { /* No authentication */
- "none"
- };
DEBUG_printf(("cupsdSetPrinterAttrs: entering name = %s, type = %x\n", p->name,
{
num_air = p->num_auth_info_required;
air = p->auth_info_required;
-
- if (!strcmp(air[0], "username"))
- auth_supported = "basic";
- else
- auth_supported = "negotiate";
}
- else if (!(p->type & CUPS_PRINTER_DISCOVERED))
+ else if ((p->type & CUPS_PRINTER_AUTHENTICATED) &&
+ (p->type & CUPS_PRINTER_DISCOVERED))
{
- if (p->type & CUPS_PRINTER_CLASS)
- snprintf(resource, sizeof(resource), "/classes/%s", p->name);
- else
- snprintf(resource, sizeof(resource), "/printers/%s", p->name);
+ num_air = 2;
+ air = air_userpass;
+ }
- if ((auth = cupsdFindBest(resource, HTTP_POST)) == NULL ||
- auth->type == CUPSD_AUTH_NONE)
- auth = cupsdFindPolicyOp(p->op_policy_ptr, IPP_PRINT_JOB);
+ if (p->type & CUPS_PRINTER_CLASS)
+ snprintf(resource, sizeof(resource), "/classes/%s", p->name);
+ else
+ snprintf(resource, sizeof(resource), "/printers/%s", p->name);
- if (auth)
- {
- int auth_type; /* Authentication type */
+ if ((auth = cupsdFindBest(resource, HTTP_POST)) == NULL ||
+ auth->type == CUPSD_AUTH_NONE)
+ auth = cupsdFindPolicyOp(p->op_policy_ptr, IPP_PRINT_JOB);
+ if (auth)
+ {
+ int auth_type; /* Authentication type */
- if ((auth_type = auth->type) == CUPSD_AUTH_DEFAULT)
- auth_type = DefaultAuthType;
- if (auth_type == CUPSD_AUTH_BASIC || auth_type == CUPSD_AUTH_BASICDIGEST)
- {
- auth_supported = "basic";
- num_air = 2;
- air = air_userpass;
- }
- else if (auth_type == CUPSD_AUTH_DIGEST)
- {
- auth_supported = "digest";
- num_air = 2;
- air = air_userpass;
- }
+ if ((auth_type = auth->type) == CUPSD_AUTH_DEFAULT)
+ auth_type = DefaultAuthType;
+
+ if (auth_type == CUPSD_AUTH_BASIC || auth_type == CUPSD_AUTH_BASICDIGEST)
+ auth_supported = "basic";
+ else if (auth_type == CUPSD_AUTH_DIGEST)
+ auth_supported = "digest";
#ifdef HAVE_GSSAPI
- else if (auth_type == CUPSD_AUTH_NEGOTIATE)
- {
- auth_supported = "negotiate";
- num_air = 1;
- air = air_negotiate;
- }
+ else if (auth_type == CUPSD_AUTH_NEGOTIATE)
+ auth_supported = "negotiate";
#endif /* HAVE_GSSAPI */
+ if (!(p->type & CUPS_PRINTER_DISCOVERED))
+ {
if (auth_type != CUPSD_AUTH_NONE)
- p->type |= CUPS_PRINTER_AUTHENTICATED;
+ p->type |= CUPS_PRINTER_AUTHENTICATED;
else
- p->type &= ~CUPS_PRINTER_AUTHENTICATED;
+ p->type &= ~CUPS_PRINTER_AUTHENTICATED;
}
- else
- p->type &= ~CUPS_PRINTER_AUTHENTICATED;
- }
- else if (p->type & CUPS_PRINTER_AUTHENTICATED)
- {
- num_air = 2;
- air = air_userpass;
}
+ else if (!(p->type & CUPS_PRINTER_DISCOVERED))
+ p->type &= ~CUPS_PRINTER_AUTHENTICATED;
/*
* Create the required IPP attributes for a printer...
* Add filters for printer...
*/
+ cupsdSetPrinterReasons(p, "-cups-missing-filter-warning,"
+ "cups-insecure-filter-warning");
+
for (filter = (char *)cupsArrayFirst(p->filters);
filter;
filter = (char *)cupsArrayNext(p->filters))
}
}
+ if ((oldattr = ippFindAttribute(oldattrs, "marker-message",
+ IPP_TAG_TEXT)) != NULL)
+ ippAddString(p->attrs, IPP_TAG_PRINTER, IPP_TAG_TEXT, "marker-message",
+ NULL, oldattr->values[0].string.text);
+
+ if ((oldattr = ippFindAttribute(oldattrs, "marker-low-levels",
+ IPP_TAG_INTEGER)) != NULL)
+ {
+ if ((attr = ippAddIntegers(p->attrs, IPP_TAG_PRINTER, IPP_TAG_INTEGER,
+ "marker-low-levels", oldattr->num_values,
+ NULL)) != NULL)
+ {
+ for (i = 0; i < oldattr->num_values; i ++)
+ attr->values[i].integer = oldattr->values[i].integer;
+ }
+ }
+
+ if ((oldattr = ippFindAttribute(oldattrs, "marker-high-levels",
+ IPP_TAG_INTEGER)) != NULL)
+ {
+ if ((attr = ippAddIntegers(p->attrs, IPP_TAG_PRINTER, IPP_TAG_INTEGER,
+ "marker-high-levels", oldattr->num_values,
+ NULL)) != NULL)
+ {
+ for (i = 0; i < oldattr->num_values; i ++)
+ attr->values[i].integer = oldattr->values[i].integer;
+ }
+ }
+
if ((oldattr = ippFindAttribute(oldattrs, "marker-names",
IPP_TAG_NAME)) != NULL)
{
if (BrowseLocalOptions)
length += 12 + strlen(BrowseLocalOptions);
- if (p->num_auth_info_required > 0)
- {
- length += 18; /* auth-info-required */
-
- for (i = 0; i < p->num_auth_info_required; i ++)
- length += strlen(p->auth_info_required[i]) + 1;
- }
-
/*
* Allocate the new string...
*/
}
}
}
-
- if (p->num_auth_info_required > 0)
- {
- strcpy(attrptr, "auth-info-required");
- attrptr += 18;
-
- for (i = 0; i < p->num_auth_info_required; i ++)
- {
- *attrptr++ = i ? ',' : '=';
- strcpy(attrptr, p->auth_info_required[i]);
- attrptr += strlen(attrptr);
- }
- }
- else
- *attrptr = '\0';
}
}
* 'cupsdSetPrinterReasons()' - Set/update the reasons strings.
*/
-void
+int /* O - 1 if something changed, 0 otherwise */
cupsdSetPrinterReasons(
cupsd_printer_t *p, /* I - Printer */
const char *s) /* I - Reasons strings */
{
- int i; /* Looping var */
+ int i, /* Looping var */
+ changed = 0; /* Did something change? */
const char *sptr; /* Pointer into reasons */
char reason[255], /* Reason string */
*rptr; /* Pointer into reason */
- if (!p || !s)
- {
- cupsdLogMessage(CUPSD_LOG_EMERG,
- "cupsdSetPrinterReasons called with p=%p and s=%p!", p, s);
- return;
- }
-
- if (LogLevel == CUPSD_LOG_DEBUG2)
- {
- cupsdLogMessage(CUPSD_LOG_DEBUG2,
- "cupsdSetPrinterReasons(p=%p(%s),s=\"%s\"", p, p->name, s);
- cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdSetPrinterReasons: num_reasons=%d",
- p->num_reasons);
- for (i = 0; i < p->num_reasons; i ++)
- cupsdLogMessage(CUPSD_LOG_DEBUG2,
- "cupsdSetPrinterReasons: reasons[%d]=%p(\"%s\")", i,
- p->reasons[i], p->reasons[i]);
- }
+ cupsdLogMessage(CUPSD_LOG_DEBUG2,
+ "cupsdSetPrinterReasons(p=%p(%s),s=\"%s\"", p, p->name, s);
if (s[0] == '-' || s[0] == '+')
{
_cupsStrFree(p->reasons[i]);
p->num_reasons = 0;
+ changed = 1;
cupsdMarkDirty(CUPSD_DIRTY_PRINTERS);
}
if (!strcmp(s, "none"))
- return;
+ return (changed);
/*
* Loop through all of the reasons...
* Found a match, so remove it...
*/
- cupsdLogMessage(CUPSD_LOG_DEBUG2,
- "cupsdSetPrinterReasons: Removing \"%s\" at index %d",
- reason, i);
-
p->num_reasons --;
+ changed = 1;
_cupsStrFree(p->reasons[i]);
if (i < p->num_reasons)
cupsdSetPrinterState(p, IPP_PRINTER_IDLE, 1);
if (strcmp(reason, "connecting-to-device"))
+ {
cupsdMarkDirty(CUPSD_DIRTY_PRINTERS);
- if (PrintcapFormat == PRINTCAP_PLIST)
- cupsdMarkDirty(CUPSD_DIRTY_PRINTCAP);
-
+ if (PrintcapFormat == PRINTCAP_PLIST)
+ cupsdMarkDirty(CUPSD_DIRTY_PRINTCAP);
+ }
break;
}
}
cupsdLogMessage(CUPSD_LOG_ALERT,
"Too many printer-state-reasons values for %s (%d)",
p->name, i + 1);
- return;
+ return (changed);
}
- cupsdLogMessage(CUPSD_LOG_DEBUG2,
- "cupsdSetPrinterReasons: Adding \"%s\" at index %d",
- reason, i);
-
p->reasons[i] = _cupsStrAlloc(reason);
p->num_reasons ++;
+ changed = 1;
if (!strcmp(reason, "paused") && p->state != IPP_PRINTER_STOPPED)
cupsdSetPrinterState(p, IPP_PRINTER_STOPPED, 1);
if (strcmp(reason, "connecting-to-device"))
+ {
cupsdMarkDirty(CUPSD_DIRTY_PRINTERS);
- if (PrintcapFormat == PRINTCAP_PLIST)
- cupsdMarkDirty(CUPSD_DIRTY_PRINTCAP);
+ if (PrintcapFormat == PRINTCAP_PLIST)
+ cupsdMarkDirty(CUPSD_DIRTY_PRINTCAP);
+ }
}
}
}
- if (LogLevel == CUPSD_LOG_DEBUG2)
- {
- cupsdLogMessage(CUPSD_LOG_DEBUG2,
- "cupsdSetPrinterReasons: NEW num_reasons=%d",
- p->num_reasons);
- for (i = 0; i < p->num_reasons; i ++)
- cupsdLogMessage(CUPSD_LOG_DEBUG2,
- "cupsdSetPrinterReasons: NEW reasons[%d]=%p(\"%s\")", i,
- p->reasons[i], p->reasons[i]);
- }
+ return (changed);
}
#endif /* __sgi */
}
+ /*
+ * Set/clear the paused reason as needed...
+ */
+
+ if (s == IPP_PRINTER_STOPPED)
+ cupsdSetPrinterReasons(p, "+paused");
+ else
+ cupsdSetPrinterReasons(p, "-paused");
+
+ /*
+ * Clear the message for the queue when going to processing...
+ */
+
+ if (s == IPP_PRINTER_PROCESSING)
+ p->state_message[0] = '\0';
+
+ /*
+ * Update the printer history...
+ */
+
cupsdAddPrinterHistory(p);
/*
* to stopped (or visa-versa)...
*/
- if ((old_state == IPP_PRINTER_STOPPED) != (s == IPP_PRINTER_STOPPED) &&
- update)
+ if (update &&
+ (old_state == IPP_PRINTER_STOPPED) != (s == IPP_PRINTER_STOPPED))
{
if (p->type & CUPS_PRINTER_CLASS)
cupsdMarkDirty(CUPSD_DIRTY_CLASSES);
cupsdStopPrinter(cupsd_printer_t *p, /* I - Printer to stop */
int update)/* I - Update printers.conf? */
{
- cupsd_job_t *job; /* Active print job */
-
-
/*
* Set the printer state...
*/
* See if we have a job printing on this printer...
*/
- if (p->job)
- {
- /*
- * Get pointer to job...
- */
-
- job = (cupsd_job_t *)p->job;
-
- /*
- * Stop it...
- */
-
- cupsdStopJob(job, 0);
-
- /*
- * Reset the state to pending...
- */
-
- job->state->values[0].integer = IPP_JOB_PENDING;
- job->state_value = IPP_JOB_PENDING;
- job->dirty = 1;
-
- cupsdMarkDirty(CUPSD_DIRTY_JOBS);
-
- cupsdAddEvent(CUPSD_EVENT_JOB_STOPPED, p, job,
- "Job stopped due to printer being paused");
- }
+ if (p->job && p->job->state_value == IPP_JOB_PROCESSING)
+ cupsdSetJobState(p->job, IPP_JOB_PENDING, CUPSD_JOB_DEFAULT,
+ "Job stopped due to printer being paused.");
}
program[1024]; /* Program/filter name */
int cost; /* Cost of filter */
mime_type_t *temptype; /* MIME type looping var */
- char filename[1024]; /* Full filter filename */
+ char filename[1024], /* Full filter filename */
+ *dirsep; /* Pointer to directory separator */
+ struct stat fileinfo; /* File information */
/*
else
snprintf(filename, sizeof(filename), "%s/filter/%s", ServerBin, program);
- if (access(filename, X_OK))
+ if (stat(filename, &fileinfo))
{
+ memset(&fileinfo, 0, sizeof(fileinfo));
+
snprintf(p->state_message, sizeof(p->state_message),
"Filter \"%s\" for printer \"%s\" not available: %s",
- program, p->name, strerror(errno));
- cupsdSetPrinterReasons(p, "+cups-missing-filter-error");
- cupsdSetPrinterState(p, IPP_PRINTER_STOPPED, 0);
+ filename, p->name, strerror(errno));
+ cupsdSetPrinterReasons(p, "+cups-missing-filter-warning");
cupsdLogMessage(CUPSD_LOG_ERROR, "%s", p->state_message);
}
+
+ /*
+ * When running as root, do additional security checks...
+ */
+
+ if (!RunUser)
+ {
+ /*
+ * Only use filters that are owned by root and do not have world write
+ * permissions.
+ */
+
+ if (fileinfo.st_uid || (fileinfo.st_mode & (S_ISUID | S_IWOTH)) != 0)
+ {
+ if (fileinfo.st_uid)
+ snprintf(p->state_message, sizeof(p->state_message),
+ "Filter \"%s\" for printer \"%s\" not owned by root",
+ filename, p->name);
+ else
+ snprintf(p->state_message, sizeof(p->state_message),
+ "Filter \"%s\" for printer \"%s\" has insecure permissions "
+ "(0%o)", filename, p->name, fileinfo.st_mode);
+
+ cupsdSetPrinterReasons(p, "+cups-insecure-filter-warning");
+
+ cupsdLogMessage(CUPSD_LOG_ERROR, "%s", p->state_message);
+ }
+ else if (fileinfo.st_mode)
+ {
+ /*
+ * Similarly, check that the parent directory is also owned by root and
+ * does not have world write permissions.
+ */
+
+ if ((dirsep = strrchr(filename, '/')) != NULL)
+ *dirsep = '\0';
+
+ if (!stat(filename, &fileinfo) &&
+ (fileinfo.st_uid ||
+ (fileinfo.st_mode & (S_ISUID | S_IWOTH)) != 0))
+ {
+ if (fileinfo.st_uid)
+ snprintf(p->state_message, sizeof(p->state_message),
+ "Filter directory \"%s\" for printer \"%s\" not owned by "
+ "root", filename, p->name);
+ else
+ snprintf(p->state_message, sizeof(p->state_message),
+ "Filter directory \"%s\" for printer \"%s\" has insecure "
+ "permissions (0%o)", filename, p->name, fileinfo.st_mode);
+
+ cupsdSetPrinterReasons(p, "+cups-insecure-filter-warning");
+
+ cupsdLogMessage(CUPSD_LOG_ERROR, "%s", p->state_message);
+ }
+ }
+ }
}
/*
mimeDeleteFilter(MimeDatabase, filter);
}
+
+ cupsdSetPrinterReasons(p, "-cups-insecure-filter-warning"
+ ",cups-missing-filter-warning");
}
if (ppd->num_sizes == 0)
{
- cupsdLogMessage(CUPSD_LOG_CRIT,
- "The PPD file for printer %s contains no media "
- "options and is therefore invalid!", p->name);
+ if (!ppdFindAttr(ppd, "APScannerOnly", NULL))
+ cupsdLogMessage(CUPSD_LOG_CRIT,
+ "The PPD file for printer %s contains no media "
+ "options and is therefore invalid!", p->name);
+
+ ippAddString(p->ppd_attrs, IPP_TAG_PRINTER, IPP_TAG_KEYWORD,
+ "media-supported", NULL, "unknown");
}
else
{
val->string.text = _cupsStrAlloc(output_bin->choices[i].choice);
}
- attr = ippAddString(p->ppd_attrs, IPP_TAG_PRINTER, IPP_TAG_KEYWORD,
- "output-bin-default", NULL, output_bin->defchoice);
+ ippAddString(p->ppd_attrs, IPP_TAG_PRINTER, IPP_TAG_KEYWORD,
+ "output-bin-default", NULL, output_bin->defchoice);
}
/*
else
p->type |= CUPS_PRINTER_SMALL;
+ if ((ppd_attr = ppdFindAttr(ppd, "APICADriver", NULL)) != NULL &&
+ ppd_attr->value && !strcasecmp(ppd_attr->value, "true"))
+ {
+ if ((ppd_attr = ppdFindAttr(ppd, "APScannerOnly", NULL)) != NULL &&
+ ppd_attr->value && !strcasecmp(ppd_attr->value, "true"))
+ p->type |= CUPS_PRINTER_SCANNER;
+ else
+ p->type |= CUPS_PRINTER_MFP;
+ }
+
/*
* Add a filter from application/vnd.cups-raw to printer/name to
* handle "raw" printing by users.