--- a/cups/ipp-support.c +++ b/cups/ipp-support.c @@ -248,6 +248,10 @@ static const char * const ipp_std_ops[] = { "CUPS-Get-Document" }, + * const ipp_alt_ext[] = + { + "ALT-DOC-FT-JOB" + }, * const ipp_tag_names[] = { /* Value/group tag names */ "zero", /* 0x00 */ @@ -2145,6 +2145,8 @@ ippOpString(ipp_op_t op) /* I - Operation ID */ return (ipp_cups_ops[op - IPP_OP_CUPS_GET_DEFAULT]); else if (op >= IPP_OP_CUPS_GET_DOCUMENT && op <= IPP_OP_CUPS_CREATE_LOCAL_PRINTER) return (ipp_cups_ops2[op - IPP_OP_CUPS_GET_DOCUMENT]); + else if (op == IPP_OP_ALT_DOC_FT_JOB) + return (ipp_alt_ext[0]); /* * No, build an "0xxxxx" operation string... @@ -2090,6 +2096,10 @@ ippOpValue(const char *name) /* I - Textual name */ if (!_cups_strcasecmp(name, ipp_cups_ops2[i])) return ((ipp_op_t)(i + 0x4027)); + for (i = 0; i < (sizeof(ipp_alt_ext) / sizeof(ipp_alt_ext[0])); i ++) + if (!_cups_strcasecmp(name, ipp_alt_ext[i])) + return ((ipp_op_t)(i + IPP_OP_ALT_DOC_FT_JOB)); + if (!_cups_strcasecmp(name, "Create-Job-Subscription")) return (IPP_OP_CREATE_JOB_SUBSCRIPTIONS); --- a/cups/ipp.h +++ b/cups/ipp.h @@ -339,7 +339,8 @@ typedef enum ipp_op_e /**** IPP operations ****/ IPP_OP_CUPS_AUTHENTICATE_JOB, /* CUPS-Authenticate-Job: Authenticate a job @since CUPS 1.2/macOS 10.5@ */ IPP_OP_CUPS_GET_PPD, /* CUPS-Get-PPD: Get a PPD file @deprecated@ */ IPP_OP_CUPS_GET_DOCUMENT = 0x4027, /* CUPS-Get-Document: Get a document file @since CUPS 1.4/macOS 10.6@ */ - IPP_OP_CUPS_CREATE_LOCAL_PRINTER /* CUPS-Create-Local-Printer: Create a local (temporary) printer @since CUPS 2.2@ */ + IPP_OP_CUPS_CREATE_LOCAL_PRINTER, /* CUPS-Create-Local-Printer: Create a local (temporary) printer @since CUPS 2.2@ */ + IPP_OP_ALT_DOC_FT_JOB = 0xF000 /* Alt Linux extension: copy document from one job to another */ # ifndef _CUPS_NO_DEPRECATED # define IPP_PRINT_JOB IPP_OP_PRINT_JOB --- a/scheduler/ipp.c +++ b/scheduler/ipp.c @@ -135,6 +135,7 @@ 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); static int validate_user(cupsd_job_t *job, cupsd_client_t *con, const char *owner, char *username, size_t userlen); +static void alt_doc_ft_job(cupsd_client_t *con, ipp_attribute_t *uri); /* @@ -612,6 +612,10 @@ cupsdProcessIPPRequest( create_local_printer(con); break; + case IPP_OP_ALT_DOC_FT_JOB : + alt_doc_ft_job(con, uri); + break; + default : cupsdAddEvent(CUPSD_EVENT_SERVER_AUDIT, NULL, NULL, "%04X %s Operation %04X (%s) not supported.", IPP_STATUS_ERROR_OPERATION_NOT_SUPPORTED, con->http->hostname, con->request->request.op.operation_id, ippOpString(con->request->request.op.operation_id)); @@ -11147,6 +11152,86 @@ validate_user(cupsd_job_t *job, /* I - Job */ con, owner) == HTTP_OK); } +static void +alt_doc_ft_job(cupsd_client_t *con, ipp_attribute_t *uri) +{ + ipp_attribute_t *attr; + cupsd_job_t *job; + + int fromjob, jobid; + int document_number; + cups_file_t *fp; + int rfd, wfd; + char buffer[8192]; + ssize_t bytes, wbytes; + http_status_t status; + + char filename[1024]; + + cupsdLogMessage(CUPSD_LOG_DEBUG2, "alt_doc_ft_job(%p[%d], %s)", con, con->number, + uri->values[0].string.text); + + /* need check for printer uri */ + + if ((attr = ippFindAttribute(con->request, "from-job", IPP_TAG_INTEGER)) == NULL) + { + send_ipp_status(con, IPP_BAD_REQUEST, + _("Got a printer-uri attribute but no from-job.")); + return; + } + + fromjob = attr->values[0].integer; + + if ((attr = ippFindAttribute(con->request, "job-id", IPP_TAG_INTEGER)) == NULL) + { + send_ipp_status(con, IPP_BAD_REQUEST, + _("Got a printer-uri attribute but no job-id.")); + return; + } + + jobid = attr->values[0].integer; + + if ((attr = ippFindAttribute(con->request, "document-number", IPP_TAG_INTEGER)) == NULL) + { + send_ipp_status(con, IPP_BAD_REQUEST, + _("Got a printer-uri attribute but no document-number.")); + return; + } + + document_number = attr->values[0].integer; + + if ((job = cupsdFindJob(jobid)) == NULL) + { + /* + * Nope - return a "not found" error... + */ + + send_ipp_status(con, IPP_NOT_FOUND, _("Job #%d does not exist."), jobid); + return; + } + + snprintf(filename, sizeof(filename), "%s/d%05d-%03d", RequestRoot, fromjob, document_number); + + if (con->filename != NULL) + cupsdLogMessage(CUPSD_LOG_DEBUG2, "alt_doc_ft_job: con->filename is %s", + con->filename); + else + cupsdLogMessage(CUPSD_LOG_DEBUG2, "alt_doc_ft_job: con->filename is NULL"); + + + con->filename = malloc(strlen(RequestRoot) + 4 + 5 + 1); + snprintf(con->filename, sizeof(filename), "%s/tmp%05d", RequestRoot, fromjob); + + if (link(filename, con->filename) == -1) + { + cupsdLogMessage(CUPSD_LOG_DEBUG2, "alt_doc_ft_job: link: %s", strerror(errno)); + send_ipp_status(con, IPP_INTERNAL_ERROR, + _("Can't make a hardlink in the filesystem.")); + return; + } + + send_document(con, uri); +} /* * End of "$Id: ipp.c 12851 2015-08-28 13:17:53Z msweet $".