diff options
author | Didier Raboud <odyx@debian.org> | 2013-06-12 14:23:32 +0200 |
---|---|---|
committer | Didier Raboud <odyx@debian.org> | 2013-06-12 14:23:32 +0200 |
commit | 6b7ae334dc7e1350c89247a3aea31c844128b970 (patch) | |
tree | 07473a9c942897c8ae5c29048e9a29dddca96e07 /test/ippserver.c | |
parent | ea5667a811b20e235ce1975e763469edd1f7f0de (diff) | |
download | cups-6b7ae334dc7e1350c89247a3aea31c844128b970.tar.gz |
Imported Upstream version 1.7~b1upstream/1.7_b1
Diffstat (limited to 'test/ippserver.c')
-rw-r--r-- | test/ippserver.c | 2174 |
1 files changed, 1061 insertions, 1113 deletions
diff --git a/test/ippserver.c b/test/ippserver.c index cce95848..a5c62733 100644 --- a/test/ippserver.c +++ b/test/ippserver.c @@ -1,9 +1,9 @@ /* - * "$Id: ippserver.c 10777 2012-12-17 22:18:10Z mike $" + * "$Id: ippserver.c 10851 2013-01-31 16:06:14Z mike $" * * Sample IPP/2.0 server for CUPS. * - * Copyright 2010-2012 by Apple Inc. + * Copyright 2010-2013 by Apple Inc. * * These coded instructions, statements, and computer programs are the * property of Apple Inc. and are protected by Federal copyright @@ -73,15 +73,31 @@ */ /* + * Disable private and deprecated stuff so we can verify that the public API + * is sufficient to implement a server. + */ + +#define _IPP_PRIVATE_STRUCTURES 0 /* Disable private IPP stuff */ +#define _CUPS_NO_DEPRECATED 1 /* Disable deprecated stuff */ + + +/* * Include necessary headers... */ -#include <cups/cups-private.h> +#include <cups/cups.h> /* Public API */ +#include <config.h> /* CUPS configuration header */ +#include <cups/string-private.h> /* For string functions */ +#include <cups/thread-private.h> /* For multithreading functions */ + +#include <sys/wait.h> + #ifdef HAVE_DNSSD # include <dns_sd.h> #endif /* HAVE_DNSSD */ #include <limits.h> #include <sys/stat.h> +#include <sys/fcntl.h> #include <poll.h> #ifdef HAVE_SYS_MOUNT_H # include <sys/mount.h> @@ -103,29 +119,29 @@ enum _ipp_preasons_e /* printer-state-reasons bit values */ { - _IPP_PRINTER_NONE = 0x0000, /* none */ - _IPP_PRINTER_OTHER = 0x0001, /* other */ - _IPP_PRINTER_COVER_OPEN = 0x0002, /* cover-open */ - _IPP_PRINTER_INPUT_TRAY_MISSING = 0x0004, + _IPP_PSTATE_NONE = 0x0000, /* none */ + _IPP_PSTATE_OTHER = 0x0001, /* other */ + _IPP_PSTATE_COVER_OPEN = 0x0002, /* cover-open */ + _IPP_PSTATE_INPUT_TRAY_MISSING = 0x0004, /* input-tray-missing */ - _IPP_PRINTER_MARKER_SUPPLY_EMPTY = 0x0008, + _IPP_PSTATE_MARKER_SUPPLY_EMPTY = 0x0008, /* marker-supply-empty */ - _IPP_PRINTER_MARKER_SUPPLY_LOW = 0x0010, + _IPP_PSTATE_MARKER_SUPPLY_LOW = 0x0010, /* marker-suply-low */ - _IPP_PRINTER_MARKER_WASTE_ALMOST_FULL = 0x0020, + _IPP_PSTATE_MARKER_WASTE_ALMOST_FULL = 0x0020, /* marker-waste-almost-full */ - _IPP_PRINTER_MARKER_WASTE_FULL = 0x0040, + _IPP_PSTATE_MARKER_WASTE_FULL = 0x0040, /* marker-waste-full */ - _IPP_PRINTER_MEDIA_EMPTY = 0x0080, /* media-empty */ - _IPP_PRINTER_MEDIA_JAM = 0x0100, /* media-jam */ - _IPP_PRINTER_MEDIA_LOW = 0x0200, /* media-low */ - _IPP_PRINTER_MEDIA_NEEDED = 0x0400, /* media-needed */ - _IPP_PRINTER_MOVING_TO_PAUSED = 0x0800, + _IPP_PSTATE_MEDIA_EMPTY = 0x0080, /* media-empty */ + _IPP_PSTATE_MEDIA_JAM = 0x0100, /* media-jam */ + _IPP_PSTATE_MEDIA_LOW = 0x0200, /* media-low */ + _IPP_PSTATE_MEDIA_NEEDED = 0x0400, /* media-needed */ + _IPP_PSTATE_MOVING_TO_PAUSED = 0x0800, /* moving-to-paused */ - _IPP_PRINTER_PAUSED = 0x1000, /* paused */ - _IPP_PRINTER_SPOOL_AREA_FULL = 0x2000,/* spool-area-full */ - _IPP_PRINTER_TONER_EMPTY = 0x4000, /* toner-empty */ - _IPP_PRINTER_TONER_LOW = 0x8000 /* toner-low */ + _IPP_PSTATE_PAUSED = 0x1000, /* paused */ + _IPP_PSTATE_SPOOL_AREA_FULL = 0x2000,/* spool-area-full */ + _IPP_PSTATE_TONER_EMPTY = 0x4000, /* toner-empty */ + _IPP_PSTATE_TONER_LOW = 0x8000 /* toner-low */ }; typedef unsigned int _ipp_preasons_t; /* Bitfield for printer-state-reasons */ @@ -196,6 +212,9 @@ typedef struct _ipp_printer_s /**** Printer data ****/ #ifdef HAVE_DNSSD DNSServiceRef common_ref, /* Shared service connection */ ipp_ref, /* Bonjour IPP service */ +# ifdef HAVE_SSL + ipps_ref, /* Bonjour IPPS service */ +# endif /* HAVE_SSL */ http_ref, /* Bonjour HTTP service */ printer_ref; /* Bonjour LPD service */ TXTRecordRef ipp_txt; /* Bonjour IPP TXT record */ @@ -205,7 +224,8 @@ typedef struct _ipp_printer_s /**** Printer data ****/ *icon, /* Icon filename */ *directory, /* Spool directory */ *hostname, /* Hostname */ - *uri; /* printer-uri-supported */ + *uri, /* printer-uri-supported */ + *command; /* Command to run with job file */ int port; /* Port */ size_t urilen; /* Length of printer URI */ ipp_t *attrs; /* Static attributes */ @@ -220,7 +240,7 @@ typedef struct _ipp_printer_s /**** Printer data ****/ struct _ipp_job_s /**** Job data ****/ { int id; /* Job ID */ - char *name, /* job-name */ + const char *name, /* job-name */ *username, /* job-originating-user-name */ *format; /* document-format */ ipp_jstate_t state; /* job-state value */ @@ -235,7 +255,7 @@ struct _ipp_job_s /**** Job data ****/ typedef struct _ipp_client_s /**** Client data ****/ { - http_t http; /* HTTP connection */ + http_t *http; /* HTTP connection */ ipp_t *request, /* IPP request */ *response; /* IPP response */ time_t start; /* Request start time */ @@ -243,6 +263,7 @@ typedef struct _ipp_client_s /**** Client data ****/ ipp_op_t operation_id; /* IPP operation-id */ char uri[1024]; /* Request URI */ http_addr_t addr; /* Client address */ + char hostname[256]; /* Client hostname */ _ipp_printer_t *printer; /* Printer */ _ipp_job_t *job; /* Current job, if any */ } _ipp_client_t; @@ -270,11 +291,12 @@ static _ipp_printer_t *create_printer(const char *servername, const char *icon, const char *docformats, int ppm, int ppm_color, int duplex, int port, + int pin, #ifdef HAVE_DNSSD - const char *regtype, + const char *subtype, #endif /* HAVE_DNSSD */ - const char *directory); -static cups_array_t *create_requested_array(_ipp_client_t *client); + const char *directory, + const char *command); static void debug_attributes(const char *title, ipp_t *ipp, int response); static void delete_client(_ipp_client_t *client); @@ -317,6 +339,7 @@ static int register_printer(_ipp_printer_t *printer, int duplex, const char *regtype); #endif /* HAVE_DNSSD */ static int respond_http(_ipp_client_t *client, http_status_t code, + const char *content_coding, const char *type, size_t length); static void respond_ipp(_ipp_client_t *client, ipp_status_t status, const char *message, ...) @@ -347,21 +370,23 @@ main(int argc, /* I - Number of command-line args */ { int i; /* Looping var */ const char *opt, /* Current option character */ + *command = NULL, /* Command to run with job files */ *servername = NULL, /* Server host name */ *name = NULL, /* Printer name */ *location = "", /* Location of printer */ *make = "Test", /* Manufacturer */ *model = "Printer", /* Model */ *icon = "printer.png", /* Icon file */ - *formats = "application/pdf,image/jpeg"; + *formats = "application/pdf,image/jpeg,image/pwg-raster"; /* Supported formats */ #ifdef HAVE_DNSSD - const char *regtype = "_ipp._tcp"; /* Bonjour service type */ + const char *subtype = "_print"; /* Bonjour service subtype */ #endif /* HAVE_DNSSD */ - int port = 8631, /* Port number (0 = auto) TODO: FIX */ + int port = 8631, /* Port number (0 = auto) */ duplex = 0, /* Duplex mode */ ppm = 10, /* Pages per minute for mono */ - ppm_color = 0; /* Pages per minute for color */ + ppm_color = 0, /* Pages per minute for color */ + pin = 0; /* PIN printing mode? */ char directory[1024] = ""; /* Spool directory */ _ipp_printer_t *printer; /* Printer object */ @@ -387,6 +412,18 @@ main(int argc, /* I - Number of command-line args */ make = argv[i]; break; + case 'P' : /* -P (PIN printing mode) */ + pin = 1; + break; + + case 'c' : /* -c command */ + i ++; + if (i >= argc) + usage(1); + + command = argv[i]; + break; + case 'd' : /* -d spool-directory */ i ++; if (i >= argc) @@ -445,11 +482,11 @@ main(int argc, /* I - Number of command-line args */ break; #ifdef HAVE_DNSSD - case 'r' : /* -r regtype */ + case 'r' : /* -r subtype */ i ++; if (i >= argc) usage(1); - regtype = argv[i]; + subtype = argv[i]; break; #endif /* HAVE_DNSSD */ @@ -508,11 +545,11 @@ main(int argc, /* I - Number of command-line args */ */ if ((printer = create_printer(servername, name, location, make, model, icon, - formats, ppm, ppm_color, duplex, port, + formats, ppm, ppm_color, duplex, port, pin, #ifdef HAVE_DNSSD - regtype, + subtype, #endif /* HAVE_DNSSD */ - directory)) == NULL) + directory, command)) == NULL) return (1); /* @@ -591,17 +628,22 @@ copy_attributes(ipp_t *to, /* I - Destination request */ if (!to || !from) return; - for (fromattr = from->attrs; fromattr; fromattr = fromattr->next) + for (fromattr = ippFirstAttribute(from); + fromattr; + fromattr = ippNextAttribute(from)) { /* * Filter attributes as needed... */ - if ((group_tag != IPP_TAG_ZERO && fromattr->group_tag != group_tag && - fromattr->group_tag != IPP_TAG_ZERO) || !fromattr->name) + ipp_tag_t fromgroup = ippGetGroupTag(fromattr); + const char *fromname = ippGetName(fromattr); + + if ((group_tag != IPP_TAG_ZERO && fromgroup != group_tag && + fromgroup != IPP_TAG_ZERO) || !fromname) continue; - if (!ra || cupsArrayFind(ra, fromattr->name)) + if (!ra || cupsArrayFind(ra, (void *)fromname)) ippCopyAttribute(to, fromattr, quickcopy); } } @@ -631,59 +673,59 @@ copy_job_attributes( { switch (job->state) { - case IPP_JOB_PENDING : + case IPP_JSTATE_PENDING : ippAddString(client->response, IPP_TAG_JOB, - IPP_TAG_KEYWORD | IPP_TAG_COPY, "job-state-reasons", + IPP_TAG_KEYWORD | IPP_TAG_CUPS_CONST, "job-state-reasons", NULL, "none"); break; - case IPP_JOB_HELD : + case IPP_JSTATE_HELD : if (job->fd >= 0) ippAddString(client->response, IPP_TAG_JOB, - IPP_TAG_KEYWORD | IPP_TAG_COPY, "job-state-reasons", - NULL, "job-incoming"); + IPP_TAG_KEYWORD | IPP_TAG_CUPS_CONST, + "job-state-reasons", NULL, "job-incoming"); else if (ippFindAttribute(job->attrs, "job-hold-until", IPP_TAG_ZERO)) ippAddString(client->response, IPP_TAG_JOB, - IPP_TAG_KEYWORD | IPP_TAG_COPY, "job-state-reasons", - NULL, "job-hold-until-specified"); + IPP_TAG_KEYWORD | IPP_TAG_CUPS_CONST, + "job-state-reasons", NULL, "job-hold-until-specified"); else ippAddString(client->response, IPP_TAG_JOB, - IPP_TAG_KEYWORD | IPP_TAG_COPY, "job-state-reasons", - NULL, "job-data-insufficient"); + IPP_TAG_KEYWORD | IPP_TAG_CUPS_CONST, + "job-state-reasons", NULL, "job-data-insufficient"); break; - case IPP_JOB_PROCESSING : + case IPP_JSTATE_PROCESSING : if (job->cancel) ippAddString(client->response, IPP_TAG_JOB, - IPP_TAG_KEYWORD | IPP_TAG_COPY, "job-state-reasons", - NULL, "processing-to-stop-point"); + IPP_TAG_KEYWORD | IPP_TAG_CUPS_CONST, + "job-state-reasons", NULL, "processing-to-stop-point"); else ippAddString(client->response, IPP_TAG_JOB, - IPP_TAG_KEYWORD | IPP_TAG_COPY, "job-state-reasons", - NULL, "job-printing"); + IPP_TAG_KEYWORD | IPP_TAG_CUPS_CONST, + "job-state-reasons", NULL, "job-printing"); break; - case IPP_JOB_STOPPED : + case IPP_JSTATE_STOPPED : ippAddString(client->response, IPP_TAG_JOB, - IPP_TAG_KEYWORD | IPP_TAG_COPY, "job-state-reasons", + IPP_TAG_KEYWORD | IPP_TAG_CUPS_CONST, "job-state-reasons", NULL, "job-stopped"); break; - case IPP_JOB_CANCELED : + case IPP_JSTATE_CANCELED : ippAddString(client->response, IPP_TAG_JOB, - IPP_TAG_KEYWORD | IPP_TAG_COPY, "job-state-reasons", + IPP_TAG_KEYWORD | IPP_TAG_CUPS_CONST, "job-state-reasons", NULL, "job-canceled-by-user"); break; - case IPP_JOB_ABORTED : + case IPP_JSTATE_ABORTED : ippAddString(client->response, IPP_TAG_JOB, - IPP_TAG_KEYWORD | IPP_TAG_COPY, "job-state-reasons", + IPP_TAG_KEYWORD | IPP_TAG_CUPS_CONST, "job-state-reasons", NULL, "aborted-by-system"); break; - case IPP_JOB_COMPLETED : + case IPP_JSTATE_COMPLETED : ippAddString(client->response, IPP_TAG_JOB, - IPP_TAG_KEYWORD | IPP_TAG_COPY, "job-state-reasons", + IPP_TAG_KEYWORD | IPP_TAG_CUPS_CONST, "job-state-reasons", NULL, "job-completed-successfully"); break; } @@ -711,8 +753,6 @@ create_client(_ipp_printer_t *printer, /* I - Printer */ int sock) /* I - Listen socket */ { _ipp_client_t *client; /* Client */ - int val; /* Parameter value */ - socklen_t addrlen; /* Length of address */ if ((client = calloc(1, sizeof(_ipp_client_t))) == NULL) @@ -721,20 +761,13 @@ create_client(_ipp_printer_t *printer, /* I - Printer */ return (NULL); } - client->printer = printer; - client->http.activity = time(NULL); - client->http.hostaddr = &(client->addr); - client->http.blocking = 1; - client->http.wait_value = 60000; + client->printer = printer; /* * Accept the client and get the remote address... */ - addrlen = sizeof(http_addr_t); - - if ((client->http.fd = accept(sock, (struct sockaddr *)&(client->addr), - &addrlen)) < 0) + if ((client->http = httpAcceptConnection(sock, 1)) == NULL) { perror("Unable to accept client connection"); @@ -743,23 +776,10 @@ create_client(_ipp_printer_t *printer, /* I - Printer */ return (NULL); } - httpAddrString(&(client->addr), client->http.hostname, - sizeof(client->http.hostname)); + httpGetHostname(client->http, client->hostname, sizeof(client->hostname)); if (Verbosity) - fprintf(stderr, "Accepted connection from %s (%s)\n", client->http.hostname, - client->http.hostaddr->addr.sa_family == AF_INET ? "IPv4" : "IPv6"); - - /* - * Using TCP_NODELAY improves responsiveness, especially on systems - * with a slow loopback interface. Since we write large buffers - * when sending print files and requests, there shouldn't be any - * performance penalty for this... - */ - - val = 1; - setsockopt(client->http.fd, IPPROTO_TCP, TCP_NODELAY, (char *)&val, - sizeof(val)); + fprintf(stderr, "Accepted connection from %s\n", client->hostname); return (client); } @@ -780,7 +800,7 @@ create_job(_ipp_client_t *client) /* I - Client */ _cupsRWLockWrite(&(client->printer->rwlock)); if (client->printer->active_job && - client->printer->active_job->state < IPP_JOB_CANCELED) + client->printer->active_job->state < IPP_JSTATE_CANCELED) { /* * Only accept a single job at a time... @@ -802,7 +822,7 @@ create_job(_ipp_client_t *client) /* I - Client */ job->printer = client->printer; job->attrs = client->request; - job->state = IPP_JOB_HELD; + job->state = IPP_JSTATE_HELD; job->fd = -1; client->request = NULL; @@ -810,8 +830,12 @@ create_job(_ipp_client_t *client) /* I - Client */ * Set all but the first two attributes to the job attributes group... */ - for (attr = job->attrs->attrs->next->next; attr; attr = attr->next) - attr->group_tag = IPP_TAG_JOB; + for (ippFirstAttribute(job->attrs), + ippNextAttribute(job->attrs), + attr = ippNextAttribute(job->attrs); + attr; + attr = ippNextAttribute(job->attrs)) + ippSetGroupTag(job->attrs, &attr, IPP_TAG_JOB); /* * Get the requesting-user-name, document format, and priority... @@ -819,22 +843,20 @@ create_job(_ipp_client_t *client) /* I - Client */ if ((attr = ippFindAttribute(job->attrs, "requesting-user-name", IPP_TAG_NAME)) != NULL) - { - _cupsStrFree(attr->name); - attr->name = _cupsStrAlloc("job-originating-user-name"); - } + ippSetName(job->attrs, &attr, "job-originating-user-name"); else - attr = ippAddString(job->attrs, IPP_TAG_JOB, IPP_TAG_NAME | IPP_TAG_COPY, + attr = ippAddString(job->attrs, IPP_TAG_JOB, + IPP_TAG_NAME | IPP_TAG_CUPS_CONST, "job-originating-user-name", NULL, "anonymous"); if (attr) - job->username = attr->values[0].string.text; + job->username = ippGetString(attr, 0, NULL); else job->username = "anonymous"; if ((attr = ippFindAttribute(job->attrs, "document-format", IPP_TAG_MIMETYPE)) != NULL) - job->format = attr->values[0].string.text; + job->format = ippGetString(attr, 0, NULL); else job->format = "application/octet-stream"; @@ -870,57 +892,24 @@ static int /* O - Listener socket or -1 on error */ create_listener(int family, /* I - Address family */ int *port) /* IO - Port number */ { - int sock, /* Listener socket */ - val; /* Socket value */ - http_addr_t address; /* Listen address */ - socklen_t addrlen; /* Length of listen address */ - - - if ((sock = socket(family, SOCK_STREAM, 0)) < 0) - return (-1); + int sock; /* Listener socket */ + http_addrlist_t *addrlist; /* Listen address */ + char service[255]; /* Service port */ - val = 1; - setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val)); - -#ifdef IPV6_V6ONLY - if (family == AF_INET6) - setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY, &val, sizeof(val)); -#endif /* IPV6_V6ONLY */ if (!*port) { - /* - * Get the auto-assigned port number for the IPv4 socket... - */ - - /* TODO: This code does not appear to work - port is always 0... */ - addrlen = sizeof(address); - if (getsockname(sock, (struct sockaddr *)&address, &addrlen)) - { - perror("getsockname() failed"); - *port = 8631; - } - else - *port = _httpAddrPort(&address); - + *port = 8000 + (getuid() % 1000); fprintf(stderr, "Listening on port %d.\n", *port); } - memset(&address, 0, sizeof(address)); - address.addr.sa_family = family; - _httpAddrSetPort(&address, *port); - - if (bind(sock, (struct sockaddr *)&address, httpAddrLength(&address))) - { - close(sock); + snprintf(service, sizeof(service), "%d", *port); + if ((addrlist = httpAddrGetList(NULL, family, service)) == NULL) return (-1); - } - if (listen(sock, 5)) - { - close(sock); - return (-1); - } + sock = httpAddrListen(&(addrlist->addr), *port); + + httpAddrFreeList(addrlist); return (sock); } @@ -1003,10 +992,12 @@ create_printer(const char *servername, /* I - Server hostname (NULL for default) int ppm_color, /* I - Pages per minute in color (0 for gray) */ int duplex, /* I - 1 = duplex, 0 = simplex */ int port, /* I - Port for listeners or 0 for auto */ + int pin, /* I - Require PIN printing */ #ifdef HAVE_DNSSD - const char *regtype, /* I - Bonjour service type */ + const char *subtype, /* I - Bonjour service subtype */ #endif /* HAVE_DNSSD */ - const char *directory) /* I - Spool directory */ + const char *directory, /* I - Spool directory */ + const char *command) /* I - Command to run on job files */ { int i, j; /* Looping vars */ _ipp_printer_t *printer; /* Printer */ @@ -1028,8 +1019,7 @@ create_printer(const char *servername, /* I - Server hostname (NULL for default) /* media-size-supported value */ ipp_t *media_col_default; /* media-col-default value */ - _ipp_value_t *media_col_value; - /* Current media-col-database value */ + int media_col_index;/* Current media-col-database value */ int k_supported; /* Maximum file size supported */ #ifdef HAVE_STATVFS struct statvfs spoolinfo; /* FS info for spool directory */ @@ -1040,10 +1030,10 @@ create_printer(const char *servername, /* I - Server hostname (NULL for default) #endif /* HAVE_STATVFS */ static const int orients[4] = /* orientation-requested-supported values */ { - IPP_PORTRAIT, - IPP_LANDSCAPE, - IPP_REVERSE_LANDSCAPE, - IPP_REVERSE_PORTRAIT + IPP_ORIENT_PORTRAIT, + IPP_ORIENT_LANDSCAPE, + IPP_ORIENT_REVERSE_LANDSCAPE, + IPP_ORIENT_REVERSE_PORTRAIT }; static const char * const versions[] =/* ipp-versions-supported values */ { @@ -1053,27 +1043,38 @@ create_printer(const char *servername, /* I - Server hostname (NULL for default) }; static const int ops[] = /* operations-supported values */ { - IPP_PRINT_JOB, - IPP_PRINT_URI, - IPP_VALIDATE_JOB, - IPP_CREATE_JOB, - IPP_SEND_DOCUMENT, - IPP_SEND_URI, - IPP_CANCEL_JOB, - IPP_GET_JOB_ATTRIBUTES, - IPP_GET_JOBS, - IPP_GET_PRINTER_ATTRIBUTES + IPP_OP_PRINT_JOB, + IPP_OP_PRINT_URI, + IPP_OP_VALIDATE_JOB, + IPP_OP_CREATE_JOB, + IPP_OP_SEND_DOCUMENT, + IPP_OP_SEND_URI, + IPP_OP_CANCEL_JOB, + IPP_OP_GET_JOB_ATTRIBUTES, + IPP_OP_GET_JOBS, + IPP_OP_GET_PRINTER_ATTRIBUTES }; static const char * const charsets[] =/* charset-supported values */ { "us-ascii", "utf-8" }; + static const char * const compressions[] =/* compression-supported values */ + { +#ifdef HAVE_LIBZ + "deflate", + "gzip", +#endif /* HAVE_LIBZ */ + "none" + }; static const char * const job_creation[] = { /* job-creation-attributes-supported values */ "copies", "ipp-attribute-fidelity", + "job-account-id", + "job-accounting-user-id", "job-name", + "job-password", "job-priority", "media", "media-col", @@ -1107,6 +1108,20 @@ create_printer(const char *servername, /* I - Server hostname (NULL for default) IPP_QUALITY_NORMAL, IPP_QUALITY_HIGH }; + static const int pwg_raster_document_resolution_supported[] = + { + 150, + 300, + 600 + }; + static const char * const pwg_raster_document_type_supported[] = + { + "black-1", + "cmyk-8", + "sgray-8", + "srgb-8", + "srgb-16" + }; static const char * const reference_uri_schemes_supported[] = { /* reference-uri-schemes-supported */ "file", @@ -1148,25 +1163,29 @@ create_printer(const char *servername, /* I - Server hostname (NULL for default) printer->ipv4 = -1; printer->ipv6 = -1; - printer->name = _cupsStrAlloc(name); + printer->name = strdup(name); #ifdef HAVE_DNSSD - printer->dnssd_name = _cupsStrRetain(printer->name); + printer->dnssd_name = strdup(printer->name); #endif /* HAVE_DNSSD */ - printer->directory = _cupsStrAlloc(directory); - printer->hostname = _cupsStrAlloc(servername ? servername : + printer->command = command ? strdup(command) : NULL; + printer->directory = strdup(directory); + printer->hostname = strdup(servername ? servername : httpGetHostname(NULL, hostname, sizeof(hostname))); printer->port = port; - printer->state = IPP_PRINTER_IDLE; - printer->state_reasons = _IPP_PRINTER_NONE; + printer->state = IPP_PSTATE_IDLE; + printer->state_reasons = _IPP_PSTATE_NONE; printer->jobs = cupsArrayNew((cups_array_func_t)compare_jobs, NULL); printer->next_job_id = 1; httpAssembleURI(HTTP_URI_CODING_ALL, uri, sizeof(uri), "ipp", NULL, - printer->hostname, printer->port, "/ipp"); - printer->uri = _cupsStrAlloc(uri); + printer->hostname, printer->port, "/ipp/print"); + printer->uri = strdup(uri); printer->urilen = strlen(uri); + if (icon) + printer->icon = strdup(icon); + _cupsRWInit(&(printer->rwlock)); /* @@ -1274,11 +1293,13 @@ create_printer(const char *servername, /* I - Server hostname (NULL for default) printer->attrs = ippNew(); /* charset-configured */ - ippAddString(printer->attrs, IPP_TAG_PRINTER, IPP_TAG_CHARSET | IPP_TAG_COPY, + ippAddString(printer->attrs, IPP_TAG_PRINTER, + IPP_TAG_CHARSET | IPP_TAG_CUPS_CONST, "charset-configured", NULL, "utf-8"); /* charset-supported */ - ippAddStrings(printer->attrs, IPP_TAG_PRINTER, IPP_TAG_CHARSET | IPP_TAG_COPY, + ippAddStrings(printer->attrs, IPP_TAG_PRINTER, + IPP_TAG_CHARSET | IPP_TAG_CUPS_CONST, "charset-supported", sizeof(charsets) / sizeof(charsets[0]), NULL, charsets); @@ -1287,8 +1308,11 @@ create_printer(const char *servername, /* I - Server hostname (NULL for default) ppm_color > 0); /* compression-supported */ - ippAddString(printer->attrs, IPP_TAG_PRINTER, IPP_TAG_KEYWORD | IPP_TAG_COPY, - "compression-supported", NULL, "none"); + ippAddStrings(printer->attrs, IPP_TAG_PRINTER, + IPP_TAG_KEYWORD | IPP_TAG_CUPS_CONST, + "compression-supported", + (int)(sizeof(compressions) / sizeof(compressions[0])), NULL, + compressions); /* copies-default */ ippAddInteger(printer->attrs, IPP_TAG_PRINTER, IPP_TAG_INTEGER, @@ -1315,16 +1339,26 @@ create_printer(const char *servername, /* I - Server hostname (NULL for default) "finishings-supported", IPP_FINISHINGS_NONE); /* generated-natural-language-supported */ - ippAddString(printer->attrs, IPP_TAG_PRINTER, IPP_TAG_LANGUAGE | IPP_TAG_COPY, + ippAddString(printer->attrs, IPP_TAG_PRINTER, + IPP_TAG_LANGUAGE | IPP_TAG_CUPS_CONST, "generated-natural-language-supported", NULL, "en"); /* ipp-versions-supported */ - ippAddStrings(printer->attrs, IPP_TAG_PRINTER, IPP_TAG_KEYWORD | IPP_TAG_COPY, + ippAddStrings(printer->attrs, IPP_TAG_PRINTER, + IPP_TAG_KEYWORD | IPP_TAG_CUPS_CONST, "ipp-versions-supported", sizeof(versions) / sizeof(versions[0]), NULL, versions); + /* job-account-id-supported */ + ippAddBoolean(printer->attrs, IPP_TAG_PRINTER, "job-account-id-supported", 1); + + /* job-accounting-user-id-supported */ + ippAddBoolean(printer->attrs, IPP_TAG_PRINTER, + "job-accounting-user-id-supported", 1); + /* job-creation-attributes-supported */ - ippAddStrings(printer->attrs, IPP_TAG_PRINTER, IPP_TAG_KEYWORD | IPP_TAG_COPY, + ippAddStrings(printer->attrs, IPP_TAG_PRINTER, + IPP_TAG_KEYWORD | IPP_TAG_CUPS_CONST, "job-creation-attributes-supported", sizeof(job_creation) / sizeof(job_creation[0]), NULL, job_creation); @@ -1333,6 +1367,10 @@ create_printer(const char *servername, /* I - Server hostname (NULL for default) ippAddRange(printer->attrs, IPP_TAG_PRINTER, "job-k-octets-supported", 0, k_supported); + /* job-password-supported */ + ippAddInteger(printer->attrs, IPP_TAG_PRINTER, IPP_TAG_INTEGER, + "job-password-supported", 4); + /* job-priority-default */ ippAddInteger(printer->attrs, IPP_TAG_PRINTER, IPP_TAG_INTEGER, "job-priority-default", 50); @@ -1342,11 +1380,13 @@ create_printer(const char *servername, /* I - Server hostname (NULL for default) "job-priority-supported", 100); /* job-sheets-default */ - ippAddString(printer->attrs, IPP_TAG_PRINTER, IPP_TAG_NAME | IPP_TAG_COPY, + ippAddString(printer->attrs, IPP_TAG_PRINTER, + IPP_TAG_NAME | IPP_TAG_CUPS_CONST, "job-sheets-default", NULL, "none"); /* job-sheets-supported */ - ippAddString(printer->attrs, IPP_TAG_PRINTER, IPP_TAG_NAME | IPP_TAG_COPY, + ippAddString(printer->attrs, IPP_TAG_PRINTER, + IPP_TAG_NAME | IPP_TAG_CUPS_CONST, "job-sheets-supported", NULL, "none"); /* media-bottom-margin-supported */ @@ -1374,7 +1414,7 @@ create_printer(const char *servername, /* I - Server hostname (NULL for default) media_col_database = ippAddCollections(printer->attrs, IPP_TAG_PRINTER, "media-col-database", num_database, NULL); - for (media_col_value = media_col_database->values, i = 0; + for (media_col_index = 0, i = 0; i < (int)(sizeof(media_col_sizes) / sizeof(media_col_sizes[0])); i ++) { @@ -1392,11 +1432,13 @@ create_printer(const char *servername, /* I - Server hostname (NULL for default) strncmp(media_type_supported[j], "photographic-", 13)) continue; - media_col_value->collection = - create_media_col(media_supported[i], media_type_supported[j], - media_col_sizes[i][0], media_col_sizes[i][1], - media_xxx_margin_supported[1]); - media_col_value ++; + ippSetCollection(printer->attrs, &media_col_database, media_col_index, + create_media_col(media_supported[i], + media_type_supported[j], + media_col_sizes[i][0], + media_col_sizes[i][1], + media_xxx_margin_supported[1])); + media_col_index ++; if (media_col_sizes[i][2] != _IPP_ENV_ONLY && (!strcmp(media_type_supported[j], "auto") || @@ -1406,11 +1448,13 @@ create_printer(const char *servername, /* I - Server hostname (NULL for default) * Add borderless version for this combination... */ - media_col_value->collection = - create_media_col(media_supported[i], media_type_supported[j], - media_col_sizes[i][0], media_col_sizes[i][1], - media_xxx_margin_supported[0]); - media_col_value ++; + ippSetCollection(printer->attrs, &media_col_database, media_col_index, + create_media_col(media_supported[i], + media_type_supported[j], + media_col_sizes[i][0], + media_col_sizes[i][1], + media_xxx_margin_supported[0])); + media_col_index ++; } } } @@ -1427,14 +1471,16 @@ create_printer(const char *servername, /* I - Server hostname (NULL for default) ippDelete(media_col_default); /* media-col-supported */ - ippAddStrings(printer->attrs, IPP_TAG_PRINTER, IPP_TAG_KEYWORD | IPP_TAG_COPY, + ippAddStrings(printer->attrs, IPP_TAG_PRINTER, + IPP_TAG_KEYWORD | IPP_TAG_CUPS_CONST, "media-col-supported", (int)(sizeof(media_col_supported) / sizeof(media_col_supported[0])), NULL, media_col_supported); /* media-default */ - ippAddString(printer->attrs, IPP_TAG_PRINTER, IPP_TAG_KEYWORD | IPP_TAG_COPY, + ippAddString(printer->attrs, IPP_TAG_PRINTER, + IPP_TAG_KEYWORD | IPP_TAG_CUPS_CONST, "media-default", NULL, media_supported[0]); /* media-left-margin-supported */ @@ -1452,7 +1498,8 @@ create_printer(const char *servername, /* I - Server hostname (NULL for default) media_xxx_margin_supported); /* media-supported */ - ippAddStrings(printer->attrs, IPP_TAG_PRINTER, IPP_TAG_KEYWORD | IPP_TAG_COPY, + ippAddStrings(printer->attrs, IPP_TAG_PRINTER, + IPP_TAG_KEYWORD | IPP_TAG_CUPS_CONST, "media-supported", (int)(sizeof(media_supported) / sizeof(media_supported[0])), NULL, media_supported); @@ -1466,8 +1513,9 @@ create_printer(const char *servername, /* I - Server hostname (NULL for default) for (i = 0; i < (int)(sizeof(media_col_sizes) / sizeof(media_col_sizes[0])); i ++) - media_size_supported->values[i].collection = - create_media_size(media_col_sizes[i][0], media_col_sizes[i][1]); + ippSetCollection(printer->attrs, &media_size_supported, i, + create_media_size(media_col_sizes[i][0], + media_col_sizes[i][1])); /* media-top-margin-supported */ ippAddIntegers(printer->attrs, IPP_TAG_PRINTER, IPP_TAG_INTEGER, @@ -1477,14 +1525,16 @@ create_printer(const char *servername, /* I - Server hostname (NULL for default) media_xxx_margin_supported); /* media-type-supported */ - ippAddStrings(printer->attrs, IPP_TAG_PRINTER, IPP_TAG_KEYWORD | IPP_TAG_COPY, + ippAddStrings(printer->attrs, IPP_TAG_PRINTER, + IPP_TAG_KEYWORD | IPP_TAG_CUPS_CONST, "media-type-supported", (int)(sizeof(media_type_supported) / sizeof(media_type_supported[0])), NULL, media_type_supported); /* multiple-document-handling-supported */ - ippAddStrings(printer->attrs, IPP_TAG_PRINTER, IPP_TAG_KEYWORD | IPP_TAG_COPY, + ippAddStrings(printer->attrs, IPP_TAG_PRINTER, + IPP_TAG_KEYWORD | IPP_TAG_CUPS_CONST, "multiple-document-handling-supported", sizeof(multiple_document_handling) / sizeof(multiple_document_handling[0]), NULL, @@ -1495,7 +1545,8 @@ create_printer(const char *servername, /* I - Server hostname (NULL for default) "multiple-document-jobs-supported", 0); /* natural-language-configured */ - ippAddString(printer->attrs, IPP_TAG_PRINTER, IPP_TAG_LANGUAGE | IPP_TAG_COPY, + ippAddString(printer->attrs, IPP_TAG_PRINTER, + IPP_TAG_LANGUAGE | IPP_TAG_CUPS_CONST, "natural-language-configured", NULL, "en"); /* number-up-default */ @@ -1519,11 +1570,13 @@ create_printer(const char *servername, /* I - Server hostname (NULL for default) "orientation-requested-supported", 4, orients); /* output-bin-default */ - ippAddString(printer->attrs, IPP_TAG_PRINTER, IPP_TAG_KEYWORD | IPP_TAG_COPY, + ippAddString(printer->attrs, IPP_TAG_PRINTER, + IPP_TAG_KEYWORD | IPP_TAG_CUPS_CONST, "output-bin-default", NULL, "face-down"); /* output-bin-supported */ - ippAddString(printer->attrs, IPP_TAG_PRINTER, IPP_TAG_KEYWORD | IPP_TAG_COPY, + ippAddString(printer->attrs, IPP_TAG_PRINTER, + IPP_TAG_KEYWORD | IPP_TAG_CUPS_CONST, "output-bin-supported", NULL, "face-down"); /* pages-per-minute */ @@ -1536,7 +1589,8 @@ create_printer(const char *servername, /* I - Server hostname (NULL for default) "pages-per-minute-color", ppm_color); /* pdl-override-supported */ - ippAddString(printer->attrs, IPP_TAG_PRINTER, IPP_TAG_KEYWORD | IPP_TAG_COPY, + ippAddString(printer->attrs, IPP_TAG_PRINTER, + IPP_TAG_KEYWORD | IPP_TAG_CUPS_CONST, "pdl-override-supported", NULL, "attempted"); /* print-quality-default */ @@ -1574,6 +1628,20 @@ create_printer(const char *servername, /* I - Server hostname (NULL for default) ippAddString(printer->attrs, IPP_TAG_PRINTER, IPP_TAG_TEXT, "printer-make-and-model", NULL, make_model); + /* printer-mandatory-job-attributes */ + if (pin) + { + static const char * const names[] = + { + "job-accounting-user-id", + "job-password" + }; + + ippAddStrings(printer->attrs, IPP_TAG_PRINTER, IPP_TAG_KEYWORD, + "printer-mandatory-job-attributes", + (int)(sizeof(names) / sizeof(names[0])), NULL, names); + } + /* printer-more-info */ ippAddString(printer->attrs, IPP_TAG_PRINTER, IPP_TAG_URI, "printer-more-info", NULL, adminurl); @@ -1594,32 +1662,60 @@ create_printer(const char *servername, /* I - Server hostname (NULL for default) ippAddString(printer->attrs, IPP_TAG_PRINTER, IPP_TAG_URI, "printer-uri-supported", NULL, uri); + /* pwg-raster-document-xxx-supported */ + for (i = 0; i < num_formats; i ++) + if (!_cups_strcasecmp(formats[i], "image/pwg-raster")) + break; + + if (i < num_formats) + { + ippAddResolutions(printer->attrs, IPP_TAG_PRINTER, + "pwg-raster-document-resolution-supported", + (int)(sizeof(pwg_raster_document_resolution_supported) / + sizeof(pwg_raster_document_resolution_supported[0])), + IPP_RES_PER_INCH, + pwg_raster_document_resolution_supported, + pwg_raster_document_resolution_supported); + ippAddString(printer->attrs, IPP_TAG_PRINTER, IPP_TAG_KEYWORD, + "pwg-raster-document-sheet-back", NULL, "normal"); + ippAddStrings(printer->attrs, IPP_TAG_PRINTER, IPP_TAG_KEYWORD, + "pwg-raster-document-type-supported", + (int)(sizeof(pwg_raster_document_type_supported) / + sizeof(pwg_raster_document_type_supported[0])), NULL, + pwg_raster_document_type_supported); + } + /* reference-uri-scheme-supported */ ippAddStrings(printer->attrs, IPP_TAG_PRINTER, - IPP_TAG_URISCHEME | IPP_TAG_COPY, + IPP_TAG_URISCHEME | IPP_TAG_CUPS_CONST, "reference-uri-schemes-supported", (int)(sizeof(reference_uri_schemes_supported) / sizeof(reference_uri_schemes_supported[0])), NULL, reference_uri_schemes_supported); /* sides-default */ - ippAddString(printer->attrs, IPP_TAG_PRINTER, IPP_TAG_KEYWORD | IPP_TAG_COPY, + ippAddString(printer->attrs, IPP_TAG_PRINTER, + IPP_TAG_KEYWORD | IPP_TAG_CUPS_CONST, "sides-default", NULL, "one-sided"); /* sides-supported */ - ippAddStrings(printer->attrs, IPP_TAG_PRINTER, IPP_TAG_KEYWORD | IPP_TAG_COPY, + ippAddStrings(printer->attrs, IPP_TAG_PRINTER, + IPP_TAG_KEYWORD | IPP_TAG_CUPS_CONST, "sides-supported", duplex ? 3 : 1, NULL, sides_supported); /* uri-authentication-supported */ - ippAddString(printer->attrs, IPP_TAG_PRINTER, IPP_TAG_KEYWORD | IPP_TAG_COPY, + ippAddString(printer->attrs, IPP_TAG_PRINTER, + IPP_TAG_KEYWORD | IPP_TAG_CUPS_CONST, "uri-authentication-supported", NULL, "none"); /* uri-security-supported */ - ippAddString(printer->attrs, IPP_TAG_PRINTER, IPP_TAG_KEYWORD | IPP_TAG_COPY, + ippAddString(printer->attrs, IPP_TAG_PRINTER, + IPP_TAG_KEYWORD | IPP_TAG_CUPS_CONST, "uri-security-supported", NULL, "none"); /* which-jobs-supported */ - ippAddStrings(printer->attrs, IPP_TAG_PRINTER, IPP_TAG_KEYWORD | IPP_TAG_COPY, + ippAddStrings(printer->attrs, IPP_TAG_PRINTER, + IPP_TAG_KEYWORD | IPP_TAG_CUPS_CONST, "which-jobs-supported", sizeof(which_jobs) / sizeof(which_jobs[0]), NULL, which_jobs); @@ -1633,7 +1729,7 @@ create_printer(const char *servername, /* I - Server hostname (NULL for default) */ if (!register_printer(printer, location, make, model, docformats, adminurl, - ppm_color > 0, duplex, regtype)) + ppm_color > 0, duplex, subtype)) goto bad_printer; #endif /* HAVE_DNSSD */ @@ -1656,208 +1752,6 @@ create_printer(const char *servername, /* I - Server hostname (NULL for default) /* - * 'create_requested_array()' - Create an array for requested-attributes. - */ - -static cups_array_t * /* O - requested-attributes array */ -create_requested_array( - _ipp_client_t *client) /* I - Client */ -{ - int i; /* Looping var */ - ipp_attribute_t *requested; /* requested-attributes attribute */ - cups_array_t *ra; /* Requested attributes array */ - char *value; /* Current value */ - - - /* - * Get the requested-attributes attribute, and return NULL if we don't - * have one... - */ - - if ((requested = ippFindAttribute(client->request, "requested-attributes", - IPP_TAG_KEYWORD)) == NULL) - return (NULL); - - /* - * If the attribute contains a single "all" keyword, return NULL... - */ - - if (requested->num_values == 1 && - !strcmp(requested->values[0].string.text, "all")) - return (NULL); - - /* - * Create an array using "strcmp" as the comparison function... - */ - - ra = cupsArrayNew((cups_array_func_t)strcmp, NULL); - - for (i = 0; i < requested->num_values; i ++) - { - value = requested->values[i].string.text; - - if (!strcmp(value, "job-template")) - { - cupsArrayAdd(ra, "copies"); - cupsArrayAdd(ra, "copies-default"); - cupsArrayAdd(ra, "copies-supported"); - cupsArrayAdd(ra, "finishings"); - cupsArrayAdd(ra, "finishings-default"); - cupsArrayAdd(ra, "finishings-supported"); - cupsArrayAdd(ra, "job-hold-until"); - cupsArrayAdd(ra, "job-hold-until-default"); - cupsArrayAdd(ra, "job-hold-until-supported"); - cupsArrayAdd(ra, "job-priority"); - cupsArrayAdd(ra, "job-priority-default"); - cupsArrayAdd(ra, "job-priority-supported"); - cupsArrayAdd(ra, "job-sheets"); - cupsArrayAdd(ra, "job-sheets-default"); - cupsArrayAdd(ra, "job-sheets-supported"); - cupsArrayAdd(ra, "media"); - cupsArrayAdd(ra, "media-col"); - cupsArrayAdd(ra, "media-col-default"); - cupsArrayAdd(ra, "media-col-supported"); - cupsArrayAdd(ra, "media-default"); - cupsArrayAdd(ra, "media-source-supported"); - cupsArrayAdd(ra, "media-supported"); - cupsArrayAdd(ra, "media-type-supported"); - cupsArrayAdd(ra, "multiple-document-handling"); - cupsArrayAdd(ra, "multiple-document-handling-default"); - cupsArrayAdd(ra, "multiple-document-handling-supported"); - cupsArrayAdd(ra, "number-up"); - cupsArrayAdd(ra, "number-up-default"); - cupsArrayAdd(ra, "number-up-supported"); - cupsArrayAdd(ra, "orientation-requested"); - cupsArrayAdd(ra, "orientation-requested-default"); - cupsArrayAdd(ra, "orientation-requested-supported"); - cupsArrayAdd(ra, "page-ranges"); - cupsArrayAdd(ra, "page-ranges-supported"); - cupsArrayAdd(ra, "printer-resolution"); - cupsArrayAdd(ra, "printer-resolution-default"); - cupsArrayAdd(ra, "printer-resolution-supported"); - cupsArrayAdd(ra, "print-quality"); - cupsArrayAdd(ra, "print-quality-default"); - cupsArrayAdd(ra, "print-quality-supported"); - cupsArrayAdd(ra, "sides"); - cupsArrayAdd(ra, "sides-default"); - cupsArrayAdd(ra, "sides-supported"); - } - else if (!strcmp(value, "job-description")) - { - cupsArrayAdd(ra, "date-time-at-completed"); - cupsArrayAdd(ra, "date-time-at-creation"); - cupsArrayAdd(ra, "date-time-at-processing"); - cupsArrayAdd(ra, "job-detailed-status-message"); - cupsArrayAdd(ra, "job-document-access-errors"); - cupsArrayAdd(ra, "job-id"); - cupsArrayAdd(ra, "job-impressions"); - cupsArrayAdd(ra, "job-impressions-completed"); - cupsArrayAdd(ra, "job-k-octets"); - cupsArrayAdd(ra, "job-k-octets-processed"); - cupsArrayAdd(ra, "job-media-sheets"); - cupsArrayAdd(ra, "job-media-sheets-completed"); - cupsArrayAdd(ra, "job-message-from-operator"); - cupsArrayAdd(ra, "job-more-info"); - cupsArrayAdd(ra, "job-name"); - cupsArrayAdd(ra, "job-originating-user-name"); - cupsArrayAdd(ra, "job-printer-up-time"); - cupsArrayAdd(ra, "job-printer-uri"); - cupsArrayAdd(ra, "job-state"); - cupsArrayAdd(ra, "job-state-message"); - cupsArrayAdd(ra, "job-state-reasons"); - cupsArrayAdd(ra, "job-uri"); - cupsArrayAdd(ra, "number-of-documents"); - cupsArrayAdd(ra, "number-of-intervening-jobs"); - cupsArrayAdd(ra, "output-device-assigned"); - cupsArrayAdd(ra, "time-at-completed"); - cupsArrayAdd(ra, "time-at-creation"); - cupsArrayAdd(ra, "time-at-processing"); - } - else if (!strcmp(value, "printer-description")) - { - cupsArrayAdd(ra, "charset-configured"); - cupsArrayAdd(ra, "charset-supported"); - cupsArrayAdd(ra, "color-supported"); - cupsArrayAdd(ra, "compression-supported"); - cupsArrayAdd(ra, "document-format-default"); - cupsArrayAdd(ra, "document-format-supported"); - cupsArrayAdd(ra, "generated-natural-language-supported"); - cupsArrayAdd(ra, "ipp-versions-supported"); - cupsArrayAdd(ra, "job-impressions-supported"); - cupsArrayAdd(ra, "job-k-octets-supported"); - cupsArrayAdd(ra, "job-media-sheets-supported"); - cupsArrayAdd(ra, "multiple-document-jobs-supported"); - cupsArrayAdd(ra, "multiple-operation-time-out"); - cupsArrayAdd(ra, "natural-language-configured"); - cupsArrayAdd(ra, "notify-attributes-supported"); - cupsArrayAdd(ra, "notify-lease-duration-default"); - cupsArrayAdd(ra, "notify-lease-duration-supported"); - cupsArrayAdd(ra, "notify-max-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"); - cupsArrayAdd(ra, "pages-per-minute"); - cupsArrayAdd(ra, "pages-per-minute-color"); - cupsArrayAdd(ra, "pdl-override-supported"); - cupsArrayAdd(ra, "printer-alert"); - cupsArrayAdd(ra, "printer-alert-description"); - cupsArrayAdd(ra, "printer-current-time"); - cupsArrayAdd(ra, "printer-driver-installer"); - cupsArrayAdd(ra, "printer-info"); - cupsArrayAdd(ra, "printer-is-accepting-jobs"); - cupsArrayAdd(ra, "printer-location"); - cupsArrayAdd(ra, "printer-make-and-model"); - cupsArrayAdd(ra, "printer-message-from-operator"); - cupsArrayAdd(ra, "printer-more-info"); - cupsArrayAdd(ra, "printer-more-info-manufacturer"); - cupsArrayAdd(ra, "printer-name"); - cupsArrayAdd(ra, "printer-state"); - cupsArrayAdd(ra, "printer-state-message"); - cupsArrayAdd(ra, "printer-state-reasons"); - cupsArrayAdd(ra, "printer-up-time"); - cupsArrayAdd(ra, "printer-uri-supported"); - cupsArrayAdd(ra, "queued-job-count"); - cupsArrayAdd(ra, "reference-uri-schemes-supported"); - cupsArrayAdd(ra, "uri-authentication-supported"); - cupsArrayAdd(ra, "uri-security-supported"); - } - else if (!strcmp(value, "printer-defaults")) - { - cupsArrayAdd(ra, "copies-default"); - cupsArrayAdd(ra, "document-format-default"); - cupsArrayAdd(ra, "finishings-default"); - cupsArrayAdd(ra, "job-hold-until-default"); - cupsArrayAdd(ra, "job-priority-default"); - cupsArrayAdd(ra, "job-sheets-default"); - cupsArrayAdd(ra, "media-default"); - cupsArrayAdd(ra, "media-col-default"); - cupsArrayAdd(ra, "number-up-default"); - cupsArrayAdd(ra, "orientation-requested-default"); - cupsArrayAdd(ra, "sides-default"); - } - else if (!strcmp(value, "subscription-template")) - { - cupsArrayAdd(ra, "notify-attributes"); - cupsArrayAdd(ra, "notify-charset"); - cupsArrayAdd(ra, "notify-events"); - cupsArrayAdd(ra, "notify-lease-duration"); - cupsArrayAdd(ra, "notify-natural-language"); - cupsArrayAdd(ra, "notify-pull-method"); - cupsArrayAdd(ra, "notify-recipient-uri"); - cupsArrayAdd(ra, "notify-time-interval"); - cupsArrayAdd(ra, "notify-user-data"); - } - else - cupsArrayAdd(ra, value); - } - - return (ra); -} - - -/* * 'debug_attributes()' - Print attributes in a request or response. */ @@ -1869,38 +1763,39 @@ debug_attributes(const char *title, /* I - Title */ ipp_tag_t group_tag; /* Current group */ ipp_attribute_t *attr; /* Current attribute */ char buffer[2048]; /* String buffer for value */ + int major, minor; /* Version */ if (Verbosity <= 1) return; fprintf(stderr, "%s:\n", title); - fprintf(stderr, " version=%d.%d\n", ipp->request.any.version[0], - ipp->request.any.version[1]); + major = ippGetVersion(ipp, &minor); + fprintf(stderr, " version=%d.%d\n", major, minor); if (type == 1) fprintf(stderr, " operation-id=%s(%04x)\n", - ippOpString(ipp->request.op.operation_id), - ipp->request.op.operation_id); + ippOpString(ippGetOperation(ipp)), ippGetOperation(ipp)); else if (type == 2) fprintf(stderr, " status-code=%s(%04x)\n", - ippErrorString(ipp->request.status.status_code), - ipp->request.status.status_code); - fprintf(stderr, " request-id=%d\n\n", ipp->request.any.request_id); + ippErrorString(ippGetStatusCode(ipp)), ippGetStatusCode(ipp)); + fprintf(stderr, " request-id=%d\n\n", ippGetRequestId(ipp)); - for (attr = ipp->attrs, group_tag = IPP_TAG_ZERO; attr; attr = attr->next) + for (attr = ippFirstAttribute(ipp), group_tag = IPP_TAG_ZERO; + attr; + attr = ippNextAttribute(ipp)) { - if (attr->group_tag != group_tag) + if (ippGetGroupTag(attr) != group_tag) { - group_tag = attr->group_tag; + group_tag = ippGetGroupTag(attr); fprintf(stderr, " %s\n", ippTagString(group_tag)); } - if (attr->name) + if (ippGetName(attr)) { ippAttributeString(attr, buffer, sizeof(buffer)); - fprintf(stderr, " %s (%s%s) %s\n", attr->name, - attr->num_values > 1 ? "1setOf " : "", - ippTagString(attr->value_tag), buffer); + fprintf(stderr, " %s (%s%s) %s\n", ippGetName(attr), + ippGetCount(attr) > 1 ? "1setOf " : "", + ippTagString(ippGetValueTag(attr)), buffer); } } } @@ -1915,27 +1810,21 @@ static void delete_client(_ipp_client_t *client) /* I - Client */ { if (Verbosity) - fprintf(stderr, "Closing connection from %s (%s)\n", client->http.hostname, - client->http.hostaddr->addr.sa_family == AF_INET ? "IPv4" : "IPv6"); + fprintf(stderr, "Closing connection from %s\n", client->hostname); /* * Flush pending writes before closing... */ - httpFlushWrite(&(client->http)); - - if (client->http.fd >= 0) - close(client->http.fd); + httpFlushWrite(client->http); /* * Free memory... */ - httpClearCookie(&(client->http)); - httpClearFields(&(client->http)); + httpClose(client->http); ippDelete(client->request); - ippDelete(client->response); free(client); @@ -1988,6 +1877,10 @@ delete_printer(_ipp_printer_t *printer) /* I - Printer */ if (printer->ipp_ref) DNSServiceRefDeallocate(printer->ipp_ref); +# ifdef HAVE_SSL + if (printer->ipps_ref) + DNSServiceRefDeallocate(printer->ipps_ref); +# endif /* HAVE_SSL */ if (printer->http_ref) DNSServiceRefDeallocate(printer->http_ref); @@ -1997,19 +1890,21 @@ delete_printer(_ipp_printer_t *printer) /* I - Printer */ TXTRecordDeallocate(&(printer->ipp_txt)); if (printer->dnssd_name) - _cupsStrFree(printer->dnssd_name); + free(printer->dnssd_name); #endif /* HAVE_DNSSD */ if (printer->name) - _cupsStrFree(printer->name); + free(printer->name); if (printer->icon) - _cupsStrFree(printer->icon); + free(printer->icon); + if (printer->command) + free(printer->command); if (printer->directory) - _cupsStrFree(printer->directory); + free(printer->directory); if (printer->hostname) - _cupsStrFree(printer->hostname); + free(printer->hostname); if (printer->uri) - _cupsStrFree(printer->uri); + free(printer->uri); ippDelete(printer->attrs); cupsArrayDelete(printer->jobs); @@ -2045,8 +1940,8 @@ dnssd_callback( fprintf(stderr, "Now using DNS-SD service name \"%s\".\n", name); /* No lock needed since only the main thread accesses/changes this */ - _cupsStrFree(printer->dnssd_name); - printer->dnssd_name = _cupsStrAlloc(name); + free(printer->dnssd_name); + printer->dnssd_name = strdup(name); } } #endif /* HAVE_DNSSD */ @@ -2069,14 +1964,15 @@ find_job(_ipp_client_t *client) /* I - Client */ if ((attr = ippFindAttribute(client->request, "job-uri", IPP_TAG_URI)) != NULL) { - if (!strncmp(attr->values[0].string.text, client->printer->uri, - client->printer->urilen) && - attr->values[0].string.text[client->printer->urilen] == '/') - key.id = atoi(attr->values[0].string.text + client->printer->urilen + 1); + const char *uri = ippGetString(attr, 0, NULL); + + if (!strncmp(uri, client->printer->uri, client->printer->urilen) && + uri[client->printer->urilen] == '/') + key.id = atoi(uri + client->printer->urilen + 1); } else if ((attr = ippFindAttribute(client->request, "job-id", IPP_TAG_INTEGER)) != NULL) - key.id = attr->values[0].integer; + key.id = ippGetInteger(attr, 0); _cupsRWLockRead(&(client->printer->rwlock)); job = (_ipp_job_t *)cupsArrayFind(client->printer->jobs, &key); @@ -2107,12 +2003,12 @@ html_escape(_ipp_client_t *client, /* I - Client */ if (*s == '&' || *s == '<') { if (s > start) - httpWrite2(&(client->http), start, s - start); + httpWrite2(client->http, start, s - start); if (*s == '&') - httpWrite2(&(client->http), "&", 5); + httpWrite2(client->http, "&", 5); else - httpWrite2(&(client->http), "<", 4); + httpWrite2(client->http, "<", 4); start = s + 1; } @@ -2121,7 +2017,7 @@ html_escape(_ipp_client_t *client, /* I - Client */ } if (s > start) - httpWrite2(&(client->http), start, s - start); + httpWrite2(client->http, start, s - start); } @@ -2158,14 +2054,14 @@ html_printf(_ipp_client_t *client, /* I - Client */ if (*format == '%') { if (format > start) - httpWrite2(&(client->http), start, format - start); + httpWrite2(client->http, start, format - start); tptr = tformat; *tptr++ = *format++; if (*format == '%') { - httpWrite2(&(client->http), "%", 1); + httpWrite2(client->http, "%", 1); format ++; continue; } @@ -2278,7 +2174,7 @@ html_printf(_ipp_client_t *client, /* I - Client */ sprintf(temp, tformat, va_arg(ap, double)); - httpWrite2(&(client->http), temp, strlen(temp)); + httpWrite2(client->http, temp, strlen(temp)); break; case 'B' : /* Integer formats */ @@ -2302,7 +2198,7 @@ html_printf(_ipp_client_t *client, /* I - Client */ else sprintf(temp, tformat, va_arg(ap, int)); - httpWrite2(&(client->http), temp, strlen(temp)); + httpWrite2(client->http, temp, strlen(temp)); break; case 'p' : /* Pointer value */ @@ -2311,7 +2207,7 @@ html_printf(_ipp_client_t *client, /* I - Client */ sprintf(temp, tformat, va_arg(ap, void *)); - httpWrite2(&(client->http), temp, strlen(temp)); + httpWrite2(client->http, temp, strlen(temp)); break; case 'c' : /* Character or character array */ @@ -2338,7 +2234,7 @@ html_printf(_ipp_client_t *client, /* I - Client */ } if (format > start) - httpWrite2(&(client->http), start, format - start); + httpWrite2(client->http, start, format - start); va_end(ap); } @@ -2360,7 +2256,7 @@ ipp_cancel_job(_ipp_client_t *client) /* I - Client */ if ((job = find_job(client)) == NULL) { - respond_ipp(client, IPP_NOT_FOUND, "Job does not exist."); + respond_ipp(client, IPP_STATUS_ERROR_NOT_FOUND, "Job does not exist."); return; } @@ -2371,18 +2267,18 @@ ipp_cancel_job(_ipp_client_t *client) /* I - Client */ switch (job->state) { - case IPP_JOB_CANCELED : - respond_ipp(client, IPP_NOT_POSSIBLE, + case IPP_JSTATE_CANCELED : + respond_ipp(client, IPP_STATUS_ERROR_NOT_POSSIBLE, "Job #%d is already canceled - can\'t cancel.", job->id); break; - case IPP_JOB_ABORTED : - respond_ipp(client, IPP_NOT_POSSIBLE, + case IPP_JSTATE_ABORTED : + respond_ipp(client, IPP_STATUS_ERROR_NOT_POSSIBLE, "Job #%d is already aborted - can\'t cancel.", job->id); break; - case IPP_JOB_COMPLETED : - respond_ipp(client, IPP_NOT_POSSIBLE, + case IPP_JSTATE_COMPLETED : + respond_ipp(client, IPP_STATUS_ERROR_NOT_POSSIBLE, "Job #%d is already completed - can\'t cancel.", job->id); break; @@ -2393,18 +2289,18 @@ ipp_cancel_job(_ipp_client_t *client) /* I - Client */ _cupsRWLockWrite(&(client->printer->rwlock)); - if (job->state == IPP_JOB_PROCESSING || - (job->state == IPP_JOB_HELD && job->fd >= 0)) + if (job->state == IPP_JSTATE_PROCESSING || + (job->state == IPP_JSTATE_HELD && job->fd >= 0)) job->cancel = 1; else { - job->state = IPP_JOB_CANCELED; + job->state = IPP_JSTATE_CANCELED; job->completed = time(NULL); } _cupsRWUnlock(&(client->printer->rwlock)); - respond_ipp(client, IPP_OK, NULL); + respond_ipp(client, IPP_STATUS_OK, NULL); break; } } @@ -2427,7 +2323,7 @@ ipp_create_job(_ipp_client_t *client) /* I - Client */ if (!valid_job_attributes(client)) { - httpFlush(&(client->http)); + httpFlush(client->http); return; } @@ -2435,9 +2331,9 @@ ipp_create_job(_ipp_client_t *client) /* I - Client */ * Do we have a file to print? */ - if (client->http.state == HTTP_POST_RECV) + if (httpGetState(client->http) == HTTP_STATE_POST_RECV) { - respond_ipp(client, IPP_BAD_REQUEST, + respond_ipp(client, IPP_STATUS_ERROR_BAD_REQUEST, "Unexpected document data following request."); return; } @@ -2448,7 +2344,8 @@ ipp_create_job(_ipp_client_t *client) /* I - Client */ if ((job = create_job(client)) == NULL) { - respond_ipp(client, IPP_PRINTER_BUSY, "Currently printing another job."); + respond_ipp(client, IPP_STATUS_ERROR_BUSY, + "Currently printing another job."); return; } @@ -2456,7 +2353,7 @@ ipp_create_job(_ipp_client_t *client) /* I - Client */ * Return the job info... */ - respond_ipp(client, IPP_OK, NULL); + respond_ipp(client, IPP_STATUS_OK, NULL); ra = cupsArrayNew((cups_array_func_t)strcmp, NULL); cupsArrayAdd(ra, "job-id"); @@ -2483,13 +2380,13 @@ ipp_get_job_attributes( if ((job = find_job(client)) == NULL) { - respond_ipp(client, IPP_NOT_FOUND, "Job not found."); + respond_ipp(client, IPP_STATUS_ERROR_NOT_FOUND, "Job not found."); return; } - respond_ipp(client, IPP_OK, NULL); + respond_ipp(client, IPP_STATUS_OK, NULL); - ra = create_requested_array(client); + ra = ippCreateRequestedArray(client->request); copy_job_attributes(client, job, ra); cupsArrayDelete(ra); } @@ -2503,6 +2400,8 @@ static void ipp_get_jobs(_ipp_client_t *client) /* I - Client */ { ipp_attribute_t *attr; /* Current attribute */ + const char *which_jobs = NULL; + /* which-jobs values */ int job_comparison; /* Job comparison */ ipp_jstate_t job_state; /* job-state value */ int first_job_id, /* First job ID */ @@ -2519,61 +2418,62 @@ ipp_get_jobs(_ipp_client_t *client) /* I - Client */ if ((attr = ippFindAttribute(client->request, "which-jobs", IPP_TAG_KEYWORD)) != NULL) - fprintf(stderr, "%s Get-Jobs which-jobs=%s", client->http.hostname, - attr->values[0].string.text); + { + which_jobs = ippGetString(attr, 0, NULL); + fprintf(stderr, "%s Get-Jobs which-jobs=%s", client->hostname, which_jobs); + } - if (!attr || !strcmp(attr->values[0].string.text, "not-completed")) + if (!which_jobs || !strcmp(which_jobs, "not-completed")) { job_comparison = -1; - job_state = IPP_JOB_STOPPED; + job_state = IPP_JSTATE_STOPPED; } - else if (!strcmp(attr->values[0].string.text, "completed")) + else if (!strcmp(which_jobs, "completed")) { job_comparison = 1; - job_state = IPP_JOB_CANCELED; + job_state = IPP_JSTATE_CANCELED; } - else if (!strcmp(attr->values[0].string.text, "aborted")) + else if (!strcmp(which_jobs, "aborted")) { job_comparison = 0; - job_state = IPP_JOB_ABORTED; + job_state = IPP_JSTATE_ABORTED; } - else if (!strcmp(attr->values[0].string.text, "all")) + else if (!strcmp(which_jobs, "all")) { job_comparison = 1; - job_state = IPP_JOB_PENDING; + job_state = IPP_JSTATE_PENDING; } - else if (!strcmp(attr->values[0].string.text, "canceled")) + else if (!strcmp(which_jobs, "canceled")) { job_comparison = 0; - job_state = IPP_JOB_CANCELED; + job_state = IPP_JSTATE_CANCELED; } - else if (!strcmp(attr->values[0].string.text, "pending")) + else if (!strcmp(which_jobs, "pending")) { job_comparison = 0; - job_state = IPP_JOB_PENDING; + job_state = IPP_JSTATE_PENDING; } - else if (!strcmp(attr->values[0].string.text, "pending-held")) + else if (!strcmp(which_jobs, "pending-held")) { job_comparison = 0; - job_state = IPP_JOB_HELD; + job_state = IPP_JSTATE_HELD; } - else if (!strcmp(attr->values[0].string.text, "processing")) + else if (!strcmp(which_jobs, "processing")) { job_comparison = 0; - job_state = IPP_JOB_PROCESSING; + job_state = IPP_JSTATE_PROCESSING; } - else if (!strcmp(attr->values[0].string.text, "processing-stopped")) + else if (!strcmp(which_jobs, "processing-stopped")) { job_comparison = 0; - job_state = IPP_JOB_STOPPED; + job_state = IPP_JSTATE_STOPPED; } else { - respond_ipp(client, IPP_ATTRIBUTES, - "The which-jobs value \"%s\" is not supported.", - attr->values[0].string.text); + respond_ipp(client, IPP_STATUS_ERROR_ATTRIBUTES_OR_VALUES, + "The which-jobs value \"%s\" is not supported.", which_jobs); ippAddString(client->response, IPP_TAG_UNSUPPORTED_GROUP, IPP_TAG_KEYWORD, - "which-jobs", NULL, attr->values[0].string.text); + "which-jobs", NULL, which_jobs); return; } @@ -2584,9 +2484,9 @@ ipp_get_jobs(_ipp_client_t *client) /* I - Client */ if ((attr = ippFindAttribute(client->request, "limit", IPP_TAG_INTEGER)) != NULL) { - limit = attr->values[0].integer; + limit = ippGetInteger(attr, 0); - fprintf(stderr, "%s Get-Jobs limit=%d", client->http.hostname, limit); + fprintf(stderr, "%s Get-Jobs limit=%d", client->hostname, limit); } else limit = 0; @@ -2594,9 +2494,9 @@ ipp_get_jobs(_ipp_client_t *client) /* I - Client */ if ((attr = ippFindAttribute(client->request, "first-job-id", IPP_TAG_INTEGER)) != NULL) { - first_job_id = attr->values[0].integer; + first_job_id = ippGetInteger(attr, 0); - fprintf(stderr, "%s Get-Jobs first-job-id=%d", client->http.hostname, + fprintf(stderr, "%s Get-Jobs first-job-id=%d", client->hostname, first_job_id); } else @@ -2611,23 +2511,25 @@ ipp_get_jobs(_ipp_client_t *client) /* I - Client */ if ((attr = ippFindAttribute(client->request, "my-jobs", IPP_TAG_BOOLEAN)) != NULL) { - fprintf(stderr, "%s Get-Jobs my-jobs=%s\n", client->http.hostname, - attr->values[0].boolean ? "true" : "false"); + int my_jobs = ippGetBoolean(attr, 0); + + fprintf(stderr, "%s Get-Jobs my-jobs=%s\n", client->hostname, + my_jobs ? "true" : "false"); - if (attr->values[0].boolean) + if (my_jobs) { if ((attr = ippFindAttribute(client->request, "requesting-user-name", IPP_TAG_NAME)) == NULL) { - respond_ipp(client, IPP_BAD_REQUEST, + respond_ipp(client, IPP_STATUS_ERROR_BAD_REQUEST, "Need requesting-user-name with my-jobs."); return; } - username = attr->values[0].string.text; + username = ippGetString(attr, 0, NULL); fprintf(stderr, "%s Get-Jobs requesting-user-name=\"%s\"\n", - client->http.hostname, username); + client->hostname, username); } } @@ -2635,21 +2537,9 @@ ipp_get_jobs(_ipp_client_t *client) /* I - Client */ * OK, build a list of jobs for this printer... */ - if ((ra = create_requested_array(client)) == NULL && - !ippFindAttribute(client->request, "requested-attributes", - IPP_TAG_KEYWORD)) - { - /* - * IPP conformance - Get-Jobs has a default requested-attributes value of - * "job-id" and "job-uri". - */ - - ra = cupsArrayNew((cups_array_func_t)strcmp, NULL); - cupsArrayAdd(ra, "job-id"); - cupsArrayAdd(ra, "job-uri"); - } + ra = ippCreateRequestedArray(client->request); - respond_ipp(client, IPP_OK, NULL); + respond_ipp(client, IPP_STATUS_OK, NULL); _cupsRWLockRead(&(client->printer->rwlock)); @@ -2665,7 +2555,8 @@ ipp_get_jobs(_ipp_client_t *client) /* I - Client */ (job_comparison == 0 && job->state != job_state) || (job_comparison > 0 && job->state < job_state) || job->id < first_job_id || - (username && job->username && _cups_strcasecmp(username, job->username))) + (username && job->username && + _cups_strcasecmp(username, job->username))) continue; if (count > 0) @@ -2697,15 +2588,15 @@ ipp_get_printer_attributes( * Send the attributes... */ - ra = create_requested_array(client); + ra = ippCreateRequestedArray(client->request); printer = client->printer; - respond_ipp(client, IPP_OK, NULL); + respond_ipp(client, IPP_STATUS_OK, NULL); _cupsRWLockRead(&(printer->rwlock)); copy_attributes(client->response, printer->attrs, ra, IPP_TAG_ZERO, - IPP_TAG_COPY); + IPP_TAG_CUPS_CONST); if (!ra || cupsArrayFind(ra, "printer-state")) ippAddInteger(client->response, IPP_TAG_PRINTER, IPP_TAG_ENUM, @@ -2713,51 +2604,51 @@ ipp_get_printer_attributes( if (!ra || cupsArrayFind(ra, "printer-state-reasons")) { - if (printer->state_reasons == _IPP_PRINTER_NONE) + if (printer->state_reasons == _IPP_PSTATE_NONE) ippAddString(client->response, IPP_TAG_PRINTER, - IPP_TAG_KEYWORD | IPP_TAG_COPY, "printer-state-reasons", - NULL, "none"); + IPP_TAG_KEYWORD | IPP_TAG_CUPS_CONST, + "printer-state-reasons", NULL, "none"); else { int num_reasons = 0;/* Number of reasons */ const char *reasons[32]; /* Reason strings */ - if (printer->state_reasons & _IPP_PRINTER_OTHER) + if (printer->state_reasons & _IPP_PSTATE_OTHER) reasons[num_reasons ++] = "other"; - if (printer->state_reasons & _IPP_PRINTER_COVER_OPEN) + if (printer->state_reasons & _IPP_PSTATE_COVER_OPEN) reasons[num_reasons ++] = "cover-open"; - if (printer->state_reasons & _IPP_PRINTER_INPUT_TRAY_MISSING) + if (printer->state_reasons & _IPP_PSTATE_INPUT_TRAY_MISSING) reasons[num_reasons ++] = "input-tray-missing"; - if (printer->state_reasons & _IPP_PRINTER_MARKER_SUPPLY_EMPTY) + if (printer->state_reasons & _IPP_PSTATE_MARKER_SUPPLY_EMPTY) reasons[num_reasons ++] = "marker-supply-empty-warning"; - if (printer->state_reasons & _IPP_PRINTER_MARKER_SUPPLY_LOW) + if (printer->state_reasons & _IPP_PSTATE_MARKER_SUPPLY_LOW) reasons[num_reasons ++] = "marker-supply-low-report"; - if (printer->state_reasons & _IPP_PRINTER_MARKER_WASTE_ALMOST_FULL) + if (printer->state_reasons & _IPP_PSTATE_MARKER_WASTE_ALMOST_FULL) reasons[num_reasons ++] = "marker-waste-almost-full-report"; - if (printer->state_reasons & _IPP_PRINTER_MARKER_WASTE_FULL) + if (printer->state_reasons & _IPP_PSTATE_MARKER_WASTE_FULL) reasons[num_reasons ++] = "marker-waste-full-warning"; - if (printer->state_reasons & _IPP_PRINTER_MEDIA_EMPTY) + if (printer->state_reasons & _IPP_PSTATE_MEDIA_EMPTY) reasons[num_reasons ++] = "media-empty-warning"; - if (printer->state_reasons & _IPP_PRINTER_MEDIA_JAM) + if (printer->state_reasons & _IPP_PSTATE_MEDIA_JAM) reasons[num_reasons ++] = "media-jam-warning"; - if (printer->state_reasons & _IPP_PRINTER_MEDIA_LOW) + if (printer->state_reasons & _IPP_PSTATE_MEDIA_LOW) reasons[num_reasons ++] = "media-low-report"; - if (printer->state_reasons & _IPP_PRINTER_MEDIA_NEEDED) + if (printer->state_reasons & _IPP_PSTATE_MEDIA_NEEDED) reasons[num_reasons ++] = "media-needed-report"; - if (printer->state_reasons & _IPP_PRINTER_MOVING_TO_PAUSED) + if (printer->state_reasons & _IPP_PSTATE_MOVING_TO_PAUSED) reasons[num_reasons ++] = "moving-to-paused"; - if (printer->state_reasons & _IPP_PRINTER_PAUSED) + if (printer->state_reasons & _IPP_PSTATE_PAUSED) reasons[num_reasons ++] = "paused"; - if (printer->state_reasons & _IPP_PRINTER_SPOOL_AREA_FULL) + if (printer->state_reasons & _IPP_PSTATE_SPOOL_AREA_FULL) reasons[num_reasons ++] = "spool-area-full"; - if (printer->state_reasons & _IPP_PRINTER_TONER_EMPTY) + if (printer->state_reasons & _IPP_PSTATE_TONER_EMPTY) reasons[num_reasons ++] = "toner-empty-warning"; - if (printer->state_reasons & _IPP_PRINTER_TONER_LOW) + if (printer->state_reasons & _IPP_PSTATE_TONER_LOW) reasons[num_reasons ++] = "toner-low-report"; ippAddStrings(client->response, IPP_TAG_PRINTER, - IPP_TAG_KEYWORD | IPP_TAG_COPY, "printer-state-reasons", - num_reasons, NULL, reasons); + IPP_TAG_KEYWORD | IPP_TAG_CUPS_CONST, + "printer-state-reasons", num_reasons, NULL, reasons); } } @@ -2769,7 +2660,7 @@ ipp_get_printer_attributes( ippAddInteger(client->response, IPP_TAG_PRINTER, IPP_TAG_INTEGER, "queued-job-count", printer->active_job && - printer->active_job->state < IPP_JOB_CANCELED); + printer->active_job->state < IPP_JSTATE_CANCELED); _cupsRWUnlock(&(printer->rwlock)); @@ -2797,7 +2688,7 @@ ipp_print_job(_ipp_client_t *client) /* I - Client */ if (!valid_job_attributes(client)) { - httpFlush(&(client->http)); + httpFlush(client->http); return; } @@ -2805,9 +2696,9 @@ ipp_print_job(_ipp_client_t *client) /* I - Client */ * Do we have a file to print? */ - if (client->http.state == HTTP_POST_SEND) + if (httpGetState(client->http) == HTTP_STATE_POST_SEND) { - respond_ipp(client, IPP_BAD_REQUEST, "No file in request."); + respond_ipp(client, IPP_STATUS_ERROR_BAD_REQUEST, "No file in request."); return; } @@ -2817,7 +2708,8 @@ ipp_print_job(_ipp_client_t *client) /* I - Client */ if ((job = create_job(client)) == NULL) { - respond_ipp(client, IPP_PRINTER_BUSY, "Currently printing another job."); + respond_ipp(client, IPP_STATUS_ERROR_BUSY, + "Currently printing another job."); return; } @@ -2831,6 +2723,9 @@ ipp_print_job(_ipp_client_t *client) /* I - Client */ else if (!_cups_strcasecmp(job->format, "image/png")) snprintf(filename, sizeof(filename), "%s/%d.png", client->printer->directory, job->id); + else if (!_cups_strcasecmp(job->format, "image/pwg-raster")) + snprintf(filename, sizeof(filename), "%s/%d.ras", + client->printer->directory, job->id); else if (!_cups_strcasecmp(job->format, "application/pdf")) snprintf(filename, sizeof(filename), "%s/%d.pdf", client->printer->directory, job->id); @@ -2843,27 +2738,27 @@ ipp_print_job(_ipp_client_t *client) /* I - Client */ if ((job->fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC, 0600)) < 0) { - job->state = IPP_JOB_ABORTED; + job->state = IPP_JSTATE_ABORTED; - respond_ipp(client, IPP_INTERNAL_ERROR, + respond_ipp(client, IPP_STATUS_ERROR_INTERNAL, "Unable to create print file: %s", strerror(errno)); return; } - while ((bytes = httpRead2(&(client->http), buffer, sizeof(buffer))) > 0) + while ((bytes = httpRead2(client->http, buffer, sizeof(buffer))) > 0) { if (write(job->fd, buffer, bytes) < bytes) { int error = errno; /* Write error */ - job->state = IPP_JOB_ABORTED; + job->state = IPP_JSTATE_ABORTED; close(job->fd); job->fd = -1; unlink(filename); - respond_ipp(client, IPP_INTERNAL_ERROR, + respond_ipp(client, IPP_STATUS_ERROR_INTERNAL, "Unable to write print file: %s", strerror(error)); return; } @@ -2875,14 +2770,15 @@ ipp_print_job(_ipp_client_t *client) /* I - Client */ * Got an error while reading the print data, so abort this job. */ - job->state = IPP_JOB_ABORTED; + job->state = IPP_JSTATE_ABORTED; close(job->fd); job->fd = -1; unlink(filename); - respond_ipp(client, IPP_INTERNAL_ERROR, "Unable to read print file."); + respond_ipp(client, IPP_STATUS_ERROR_INTERNAL, + "Unable to read print file."); return; } @@ -2890,19 +2786,19 @@ ipp_print_job(_ipp_client_t *client) /* I - Client */ { int error = errno; /* Write error */ - job->state = IPP_JOB_ABORTED; + job->state = IPP_JSTATE_ABORTED; job->fd = -1; unlink(filename); - respond_ipp(client, IPP_INTERNAL_ERROR, "Unable to write print file: %s", - strerror(error)); + respond_ipp(client, IPP_STATUS_ERROR_INTERNAL, + "Unable to write print file: %s", strerror(error)); return; } job->fd = -1; job->filename = strdup(filename); - job->state = IPP_JOB_PENDING; + job->state = IPP_JSTATE_PENDING; /* * Process the job... @@ -2911,8 +2807,8 @@ ipp_print_job(_ipp_client_t *client) /* I - Client */ #if 0 if (!_cupsThreadCreate((_cups_thread_func_t)process_job, job)) { - job->state = IPP_JOB_ABORTED; - respond_ipp(client, IPP_INTERNAL_ERROR, "Unable to process job."); + job->state = IPP_JSTATE_ABORTED; + respond_ipp(client, IPP_STATUS_ERROR_INTERNAL, "Unable to process job."); return; } @@ -2924,7 +2820,7 @@ ipp_print_job(_ipp_client_t *client) /* I - Client */ * Return the job info... */ - respond_ipp(client, IPP_OK, NULL); + respond_ipp(client, IPP_STATUS_OK, NULL); ra = cupsArrayNew((cups_array_func_t)strcmp, NULL); cupsArrayAdd(ra, "job-id"); @@ -2979,7 +2875,7 @@ ipp_print_uri(_ipp_client_t *client) /* I - Client */ if (!valid_job_attributes(client)) { - httpFlush(&(client->http)); + httpFlush(client->http); return; } @@ -2987,9 +2883,9 @@ ipp_print_uri(_ipp_client_t *client) /* I - Client */ * Do we have a file to print? */ - if (client->http.state == HTTP_POST_RECV) + if (httpGetState(client->http) == HTTP_STATE_POST_RECV) { - respond_ipp(client, IPP_BAD_REQUEST, + respond_ipp(client, IPP_STATUS_ERROR_BAD_REQUEST, "Unexpected document data following request."); return; } @@ -3001,24 +2897,25 @@ ipp_print_uri(_ipp_client_t *client) /* I - Client */ if ((uri = ippFindAttribute(client->request, "document-uri", IPP_TAG_URI)) == NULL) { - respond_ipp(client, IPP_BAD_REQUEST, "Missing document-uri."); + respond_ipp(client, IPP_STATUS_ERROR_BAD_REQUEST, "Missing document-uri."); return; } - if (uri->num_values != 1) + if (ippGetCount(uri) != 1) { - respond_ipp(client, IPP_BAD_REQUEST, "Too many document-uri values."); + respond_ipp(client, IPP_STATUS_ERROR_BAD_REQUEST, + "Too many document-uri values."); return; } - uri_status = httpSeparateURI(HTTP_URI_CODING_ALL, uri->values[0].string.text, + uri_status = httpSeparateURI(HTTP_URI_CODING_ALL, ippGetString(uri, 0, NULL), scheme, sizeof(scheme), userpass, sizeof(userpass), hostname, sizeof(hostname), &port, resource, sizeof(resource)); - if (uri_status < HTTP_URI_OK) + if (uri_status < HTTP_URI_STATUS_OK) { - respond_ipp(client, IPP_BAD_REQUEST, "Bad document-uri: %s", - uri_status_strings[uri_status - HTTP_URI_OVERFLOW]); + respond_ipp(client, IPP_STATUS_ERROR_BAD_REQUEST, "Bad document-uri: %s", + uri_status_strings[uri_status - HTTP_URI_STATUS_OVERFLOW]); return; } @@ -3028,15 +2925,15 @@ ipp_print_uri(_ipp_client_t *client) /* I - Client */ #endif /* HAVE_SSL */ strcmp(scheme, "http")) { - respond_ipp(client, IPP_URI_SCHEME, "URI scheme \"%s\" not supported.", - scheme); + respond_ipp(client, IPP_STATUS_ERROR_URI_SCHEME, + "URI scheme \"%s\" not supported.", scheme); return; } if (!strcmp(scheme, "file") && access(resource, R_OK)) { - respond_ipp(client, IPP_DOCUMENT_ACCESS_ERROR, "Unable to access URI: %s", - strerror(errno)); + respond_ipp(client, IPP_STATUS_ERROR_DOCUMENT_ACCESS, + "Unable to access URI: %s", strerror(errno)); return; } @@ -3046,7 +2943,8 @@ ipp_print_uri(_ipp_client_t *client) /* I - Client */ if ((job = create_job(client)) == NULL) { - respond_ipp(client, IPP_PRINTER_BUSY, "Currently printing another job."); + respond_ipp(client, IPP_STATUS_ERROR_BUSY, + "Currently printing another job."); return; } @@ -3072,9 +2970,9 @@ ipp_print_uri(_ipp_client_t *client) /* I - Client */ if ((job->fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC, 0600)) < 0) { - job->state = IPP_JOB_ABORTED; + job->state = IPP_JSTATE_ABORTED; - respond_ipp(client, IPP_INTERNAL_ERROR, + respond_ipp(client, IPP_STATUS_ERROR_INTERNAL, "Unable to create print file: %s", strerror(errno)); return; } @@ -3083,8 +2981,8 @@ ipp_print_uri(_ipp_client_t *client) /* I - Client */ { if ((infile = open(resource, O_RDONLY)) < 0) { - respond_ipp(client, IPP_DOCUMENT_ACCESS_ERROR, "Unable to access URI: %s", - strerror(errno)); + respond_ipp(client, IPP_STATUS_ERROR_DOCUMENT_ACCESS, + "Unable to access URI: %s", strerror(errno)); return; } @@ -3097,7 +2995,7 @@ ipp_print_uri(_ipp_client_t *client) /* I - Client */ { int error = errno; /* Write error */ - job->state = IPP_JOB_ABORTED; + job->state = IPP_JSTATE_ABORTED; close(job->fd); job->fd = -1; @@ -3105,7 +3003,7 @@ ipp_print_uri(_ipp_client_t *client) /* I - Client */ unlink(filename); close(infile); - respond_ipp(client, IPP_INTERNAL_ERROR, + respond_ipp(client, IPP_STATUS_ERROR_INTERNAL, "Unable to write print file: %s", strerror(error)); return; } @@ -3118,17 +3016,18 @@ ipp_print_uri(_ipp_client_t *client) /* I - Client */ { #ifdef HAVE_SSL if (port == 443 || !strcmp(scheme, "https")) - encryption = HTTP_ENCRYPT_ALWAYS; + encryption = HTTP_ENCRYPTION_ALWAYS; else #endif /* HAVE_SSL */ - encryption = HTTP_ENCRYPT_IF_REQUESTED; + encryption = HTTP_ENCRYPTION_IF_REQUESTED; - if ((http = httpConnectEncrypt(hostname, port, encryption)) == NULL) + if ((http = httpConnect2(hostname, port, NULL, AF_UNSPEC, encryption, + 1, 30000, NULL)) == NULL) { - respond_ipp(client, IPP_DOCUMENT_ACCESS_ERROR, + respond_ipp(client, IPP_STATUS_ERROR_DOCUMENT_ACCESS, "Unable to connect to %s: %s", hostname, cupsLastErrorString()); - job->state = IPP_JOB_ABORTED; + job->state = IPP_JSTATE_ABORTED; close(job->fd); job->fd = -1; @@ -3141,10 +3040,10 @@ ipp_print_uri(_ipp_client_t *client) /* I - Client */ httpSetField(http, HTTP_FIELD_ACCEPT_LANGUAGE, "en"); if (httpGet(http, resource)) { - respond_ipp(client, IPP_DOCUMENT_ACCESS_ERROR, "Unable to GET URI: %s", - strerror(errno)); + respond_ipp(client, IPP_STATUS_ERROR_DOCUMENT_ACCESS, + "Unable to GET URI: %s", strerror(errno)); - job->state = IPP_JOB_ABORTED; + job->state = IPP_JSTATE_ABORTED; close(job->fd); job->fd = -1; @@ -3154,14 +3053,14 @@ ipp_print_uri(_ipp_client_t *client) /* I - Client */ return; } - while ((status = httpUpdate(http)) == HTTP_CONTINUE); + while ((status = httpUpdate(http)) == HTTP_STATUS_CONTINUE); - if (status != HTTP_OK) + if (status != HTTP_STATUS_OK) { - respond_ipp(client, IPP_DOCUMENT_ACCESS_ERROR, "Unable to GET URI: %s", - httpStatus(status)); + respond_ipp(client, IPP_STATUS_ERROR_DOCUMENT_ACCESS, + "Unable to GET URI: %s", httpStatus(status)); - job->state = IPP_JOB_ABORTED; + job->state = IPP_JSTATE_ABORTED; close(job->fd); job->fd = -1; @@ -3177,7 +3076,7 @@ ipp_print_uri(_ipp_client_t *client) /* I - Client */ { int error = errno; /* Write error */ - job->state = IPP_JOB_ABORTED; + job->state = IPP_JSTATE_ABORTED; close(job->fd); job->fd = -1; @@ -3185,7 +3084,7 @@ ipp_print_uri(_ipp_client_t *client) /* I - Client */ unlink(filename); httpClose(http); - respond_ipp(client, IPP_INTERNAL_ERROR, + respond_ipp(client, IPP_STATUS_ERROR_INTERNAL, "Unable to write print file: %s", strerror(error)); return; } @@ -3198,19 +3097,19 @@ ipp_print_uri(_ipp_client_t *client) /* I - Client */ { int error = errno; /* Write error */ - job->state = IPP_JOB_ABORTED; + job->state = IPP_JSTATE_ABORTED; job->fd = -1; unlink(filename); - respond_ipp(client, IPP_INTERNAL_ERROR, "Unable to write print file: %s", - strerror(error)); + respond_ipp(client, IPP_STATUS_ERROR_INTERNAL, + "Unable to write print file: %s", strerror(error)); return; } job->fd = -1; job->filename = strdup(filename); - job->state = IPP_JOB_PENDING; + job->state = IPP_JSTATE_PENDING; /* * Process the job... @@ -3219,8 +3118,8 @@ ipp_print_uri(_ipp_client_t *client) /* I - Client */ #if 0 if (!_cupsThreadCreate((_cups_thread_func_t)process_job, job)) { - job->state = IPP_JOB_ABORTED; - respond_ipp(client, IPP_INTERNAL_ERROR, "Unable to process job."); + job->state = IPP_JSTATE_ABORTED; + respond_ipp(client, IPP_STATUS_ERROR_INTERNAL, "Unable to process job."); return; } @@ -3232,7 +3131,7 @@ ipp_print_uri(_ipp_client_t *client) /* I - Client */ * Return the job info... */ - respond_ipp(client, IPP_OK, NULL); + respond_ipp(client, IPP_STATUS_OK, NULL); ra = cupsArrayNew((cups_array_func_t)strcmp, NULL); cupsArrayAdd(ra, "job-id"); @@ -3267,8 +3166,8 @@ ipp_send_document(_ipp_client_t *client)/* I - Client */ if ((job = find_job(client)) == NULL) { - respond_ipp(client, IPP_NOT_FOUND, "Job does not exist."); - httpFlush(&(client->http)); + respond_ipp(client, IPP_STATUS_ERROR_NOT_FOUND, "Job does not exist."); + httpFlush(client->http); return; } @@ -3277,33 +3176,34 @@ ipp_send_document(_ipp_client_t *client)/* I - Client */ * in a non-pending state... */ - if (job->state > IPP_JOB_HELD) + if (job->state > IPP_JSTATE_HELD) { - respond_ipp(client, IPP_NOT_POSSIBLE, "Job is not in a pending state."); - httpFlush(&(client->http)); + respond_ipp(client, IPP_STATUS_ERROR_NOT_POSSIBLE, + "Job is not in a pending state."); + httpFlush(client->http); return; } else if (job->filename || job->fd >= 0) { - respond_ipp(client, IPP_MULTIPLE_JOBS_NOT_SUPPORTED, + respond_ipp(client, IPP_STATUS_ERROR_MULTIPLE_JOBS_NOT_SUPPORTED, "Multiple document jobs are not supported."); - httpFlush(&(client->http)); + httpFlush(client->http); return; } if ((attr = ippFindAttribute(client->request, "last-document", IPP_TAG_ZERO)) == NULL) { - respond_ipp(client, IPP_BAD_REQUEST, + respond_ipp(client, IPP_STATUS_ERROR_BAD_REQUEST, "Missing required last-document attribute."); - httpFlush(&(client->http)); + httpFlush(client->http); return; } - else if (attr->value_tag != IPP_TAG_BOOLEAN || attr->num_values != 1 || - !attr->values[0].boolean) + else if (ippGetValueTag(attr) != IPP_TAG_BOOLEAN || ippGetCount(attr) != 1 || + !ippGetBoolean(attr, 0)) { respond_unsupported(client, attr); - httpFlush(&(client->http)); + httpFlush(client->http); return; } @@ -3313,7 +3213,7 @@ ipp_send_document(_ipp_client_t *client)/* I - Client */ if (!valid_doc_attributes(client)) { - httpFlush(&(client->http)); + httpFlush(client->http); return; } @@ -3325,7 +3225,7 @@ ipp_send_document(_ipp_client_t *client)/* I - Client */ if ((attr = ippFindAttribute(job->attrs, "document-format", IPP_TAG_MIMETYPE)) != NULL) - job->format = attr->values[0].string.text; + job->format = ippGetString(attr, 0, NULL); else job->format = "application/octet-stream"; @@ -3355,27 +3255,27 @@ ipp_send_document(_ipp_client_t *client)/* I - Client */ if (job->fd < 0) { - job->state = IPP_JOB_ABORTED; + job->state = IPP_JSTATE_ABORTED; - respond_ipp(client, IPP_INTERNAL_ERROR, + respond_ipp(client, IPP_STATUS_ERROR_INTERNAL, "Unable to create print file: %s", strerror(errno)); return; } - while ((bytes = httpRead2(&(client->http), buffer, sizeof(buffer))) > 0) + while ((bytes = httpRead2(client->http, buffer, sizeof(buffer))) > 0) { if (write(job->fd, buffer, bytes) < bytes) { int error = errno; /* Write error */ - job->state = IPP_JOB_ABORTED; + job->state = IPP_JSTATE_ABORTED; close(job->fd); job->fd = -1; unlink(filename); - respond_ipp(client, IPP_INTERNAL_ERROR, + respond_ipp(client, IPP_STATUS_ERROR_INTERNAL, "Unable to write print file: %s", strerror(error)); return; } @@ -3387,14 +3287,15 @@ ipp_send_document(_ipp_client_t *client)/* I - Client */ * Got an error while reading the print data, so abort this job. */ - job->state = IPP_JOB_ABORTED; + job->state = IPP_JSTATE_ABORTED; close(job->fd); job->fd = -1; unlink(filename); - respond_ipp(client, IPP_INTERNAL_ERROR, "Unable to read print file."); + respond_ipp(client, IPP_STATUS_ERROR_INTERNAL, + "Unable to read print file."); return; } @@ -3402,13 +3303,13 @@ ipp_send_document(_ipp_client_t *client)/* I - Client */ { int error = errno; /* Write error */ - job->state = IPP_JOB_ABORTED; + job->state = IPP_JSTATE_ABORTED; job->fd = -1; unlink(filename); - respond_ipp(client, IPP_INTERNAL_ERROR, "Unable to write print file: %s", - strerror(error)); + respond_ipp(client, IPP_STATUS_ERROR_INTERNAL, + "Unable to write print file: %s", strerror(error)); return; } @@ -3416,7 +3317,7 @@ ipp_send_document(_ipp_client_t *client)/* I - Client */ job->fd = -1; job->filename = strdup(filename); - job->state = IPP_JOB_PENDING; + job->state = IPP_JSTATE_PENDING; _cupsRWUnlock(&(client->printer->rwlock)); @@ -3427,8 +3328,8 @@ ipp_send_document(_ipp_client_t *client)/* I - Client */ #if 0 if (!_cupsThreadCreate((_cups_thread_func_t)process_job, job)) { - job->state = IPP_JOB_ABORTED; - respond_ipp(client, IPP_INTERNAL_ERROR, "Unable to process job."); + job->state = IPP_JSTATE_ABORTED; + respond_ipp(client, IPP_STATUS_ERROR_INTERNAL, "Unable to process job."); return; } @@ -3440,7 +3341,7 @@ ipp_send_document(_ipp_client_t *client)/* I - Client */ * Return the job info... */ - respond_ipp(client, IPP_OK, NULL); + respond_ipp(client, IPP_STATUS_OK, NULL); ra = cupsArrayNew((cups_array_func_t)strcmp, NULL); cupsArrayAdd(ra, "job-id"); @@ -3497,8 +3398,8 @@ ipp_send_uri(_ipp_client_t *client) /* I - Client */ if ((job = find_job(client)) == NULL) { - respond_ipp(client, IPP_NOT_FOUND, "Job does not exist."); - httpFlush(&(client->http)); + respond_ipp(client, IPP_STATUS_ERROR_NOT_FOUND, "Job does not exist."); + httpFlush(client->http); return; } @@ -3507,33 +3408,34 @@ ipp_send_uri(_ipp_client_t *client) /* I - Client */ * in a non-pending state... */ - if (job->state > IPP_JOB_HELD) + if (job->state > IPP_JSTATE_HELD) { - respond_ipp(client, IPP_NOT_POSSIBLE, "Job is not in a pending state."); - httpFlush(&(client->http)); + respond_ipp(client, IPP_STATUS_ERROR_NOT_POSSIBLE, + "Job is not in a pending state."); + httpFlush(client->http); return; } else if (job->filename || job->fd >= 0) { - respond_ipp(client, IPP_MULTIPLE_JOBS_NOT_SUPPORTED, + respond_ipp(client, IPP_STATUS_ERROR_MULTIPLE_JOBS_NOT_SUPPORTED, "Multiple document jobs are not supported."); - httpFlush(&(client->http)); + httpFlush(client->http); return; } if ((attr = ippFindAttribute(client->request, "last-document", IPP_TAG_ZERO)) == NULL) { - respond_ipp(client, IPP_BAD_REQUEST, + respond_ipp(client, IPP_STATUS_ERROR_BAD_REQUEST, "Missing required last-document attribute."); - httpFlush(&(client->http)); + httpFlush(client->http); return; } - else if (attr->value_tag != IPP_TAG_BOOLEAN || attr->num_values != 1 || - !attr->values[0].boolean) + else if (ippGetValueTag(attr) != IPP_TAG_BOOLEAN || ippGetCount(attr) != 1 || + !ippGetBoolean(attr, 0)) { respond_unsupported(client, attr); - httpFlush(&(client->http)); + httpFlush(client->http); return; } @@ -3543,7 +3445,7 @@ ipp_send_uri(_ipp_client_t *client) /* I - Client */ if (!valid_doc_attributes(client)) { - httpFlush(&(client->http)); + httpFlush(client->http); return; } @@ -3551,9 +3453,9 @@ ipp_send_uri(_ipp_client_t *client) /* I - Client */ * Do we have a file to print? */ - if (client->http.state == HTTP_POST_RECV) + if (httpGetState(client->http) == HTTP_STATE_POST_RECV) { - respond_ipp(client, IPP_BAD_REQUEST, + respond_ipp(client, IPP_STATUS_ERROR_BAD_REQUEST, "Unexpected document data following request."); return; } @@ -3565,24 +3467,25 @@ ipp_send_uri(_ipp_client_t *client) /* I - Client */ if ((uri = ippFindAttribute(client->request, "document-uri", IPP_TAG_URI)) == NULL) { - respond_ipp(client, IPP_BAD_REQUEST, "Missing document-uri."); + respond_ipp(client, IPP_STATUS_ERROR_BAD_REQUEST, "Missing document-uri."); return; } - if (uri->num_values != 1) + if (ippGetCount(uri) != 1) { - respond_ipp(client, IPP_BAD_REQUEST, "Too many document-uri values."); + respond_ipp(client, IPP_STATUS_ERROR_BAD_REQUEST, + "Too many document-uri values."); return; } - uri_status = httpSeparateURI(HTTP_URI_CODING_ALL, uri->values[0].string.text, + uri_status = httpSeparateURI(HTTP_URI_CODING_ALL, ippGetString(uri, 0, NULL), scheme, sizeof(scheme), userpass, sizeof(userpass), hostname, sizeof(hostname), &port, resource, sizeof(resource)); - if (uri_status < HTTP_URI_OK) + if (uri_status < HTTP_URI_STATUS_OK) { - respond_ipp(client, IPP_BAD_REQUEST, "Bad document-uri: %s", - uri_status_strings[uri_status - HTTP_URI_OVERFLOW]); + respond_ipp(client, IPP_STATUS_ERROR_BAD_REQUEST, "Bad document-uri: %s", + uri_status_strings[uri_status - HTTP_URI_STATUS_OVERFLOW]); return; } @@ -3592,15 +3495,15 @@ ipp_send_uri(_ipp_client_t *client) /* I - Client */ #endif /* HAVE_SSL */ strcmp(scheme, "http")) { - respond_ipp(client, IPP_URI_SCHEME, "URI scheme \"%s\" not supported.", - scheme); + respond_ipp(client, IPP_STATUS_ERROR_URI_SCHEME, + "URI scheme \"%s\" not supported.", scheme); return; } if (!strcmp(scheme, "file") && access(resource, R_OK)) { - respond_ipp(client, IPP_DOCUMENT_ACCESS_ERROR, "Unable to access URI: %s", - strerror(errno)); + respond_ipp(client, IPP_STATUS_ERROR_DOCUMENT_ACCESS, + "Unable to access URI: %s", strerror(errno)); return; } @@ -3612,7 +3515,7 @@ ipp_send_uri(_ipp_client_t *client) /* I - Client */ if ((attr = ippFindAttribute(job->attrs, "document-format", IPP_TAG_MIMETYPE)) != NULL) - job->format = attr->values[0].string.text; + job->format = ippGetString(attr, 0, NULL); else job->format = "application/octet-stream"; @@ -3642,9 +3545,9 @@ ipp_send_uri(_ipp_client_t *client) /* I - Client */ if (job->fd < 0) { - job->state = IPP_JOB_ABORTED; + job->state = IPP_JSTATE_ABORTED; - respond_ipp(client, IPP_INTERNAL_ERROR, + respond_ipp(client, IPP_STATUS_ERROR_INTERNAL, "Unable to create print file: %s", strerror(errno)); return; } @@ -3653,8 +3556,8 @@ ipp_send_uri(_ipp_client_t *client) /* I - Client */ { if ((infile = open(resource, O_RDONLY)) < 0) { - respond_ipp(client, IPP_DOCUMENT_ACCESS_ERROR, "Unable to access URI: %s", - strerror(errno)); + respond_ipp(client, IPP_STATUS_ERROR_DOCUMENT_ACCESS, + "Unable to access URI: %s", strerror(errno)); return; } @@ -3667,7 +3570,7 @@ ipp_send_uri(_ipp_client_t *client) /* I - Client */ { int error = errno; /* Write error */ - job->state = IPP_JOB_ABORTED; + job->state = IPP_JSTATE_ABORTED; close(job->fd); job->fd = -1; @@ -3675,7 +3578,7 @@ ipp_send_uri(_ipp_client_t *client) /* I - Client */ unlink(filename); close(infile); - respond_ipp(client, IPP_INTERNAL_ERROR, + respond_ipp(client, IPP_STATUS_ERROR_INTERNAL, "Unable to write print file: %s", strerror(error)); return; } @@ -3688,17 +3591,18 @@ ipp_send_uri(_ipp_client_t *client) /* I - Client */ { #ifdef HAVE_SSL if (port == 443 || !strcmp(scheme, "https")) - encryption = HTTP_ENCRYPT_ALWAYS; + encryption = HTTP_ENCRYPTION_ALWAYS; else #endif /* HAVE_SSL */ - encryption = HTTP_ENCRYPT_IF_REQUESTED; + encryption = HTTP_ENCRYPTION_IF_REQUESTED; - if ((http = httpConnectEncrypt(hostname, port, encryption)) == NULL) + if ((http = httpConnect2(hostname, port, NULL, AF_UNSPEC, encryption, + 1, 30000, NULL)) == NULL) { - respond_ipp(client, IPP_DOCUMENT_ACCESS_ERROR, + respond_ipp(client, IPP_STATUS_ERROR_DOCUMENT_ACCESS, "Unable to connect to %s: %s", hostname, cupsLastErrorString()); - job->state = IPP_JOB_ABORTED; + job->state = IPP_JSTATE_ABORTED; close(job->fd); job->fd = -1; @@ -3711,10 +3615,10 @@ ipp_send_uri(_ipp_client_t *client) /* I - Client */ httpSetField(http, HTTP_FIELD_ACCEPT_LANGUAGE, "en"); if (httpGet(http, resource)) { - respond_ipp(client, IPP_DOCUMENT_ACCESS_ERROR, "Unable to GET URI: %s", - strerror(errno)); + respond_ipp(client, IPP_STATUS_ERROR_DOCUMENT_ACCESS, + "Unable to GET URI: %s", strerror(errno)); - job->state = IPP_JOB_ABORTED; + job->state = IPP_JSTATE_ABORTED; close(job->fd); job->fd = -1; @@ -3724,14 +3628,14 @@ ipp_send_uri(_ipp_client_t *client) /* I - Client */ return; } - while ((status = httpUpdate(http)) == HTTP_CONTINUE); + while ((status = httpUpdate(http)) == HTTP_STATUS_CONTINUE); - if (status != HTTP_OK) + if (status != HTTP_STATUS_OK) { - respond_ipp(client, IPP_DOCUMENT_ACCESS_ERROR, "Unable to GET URI: %s", - httpStatus(status)); + respond_ipp(client, IPP_STATUS_ERROR_DOCUMENT_ACCESS, + "Unable to GET URI: %s", httpStatus(status)); - job->state = IPP_JOB_ABORTED; + job->state = IPP_JSTATE_ABORTED; close(job->fd); job->fd = -1; @@ -3747,7 +3651,7 @@ ipp_send_uri(_ipp_client_t *client) /* I - Client */ { int error = errno; /* Write error */ - job->state = IPP_JOB_ABORTED; + job->state = IPP_JSTATE_ABORTED; close(job->fd); job->fd = -1; @@ -3755,7 +3659,7 @@ ipp_send_uri(_ipp_client_t *client) /* I - Client */ unlink(filename); httpClose(http); - respond_ipp(client, IPP_INTERNAL_ERROR, + respond_ipp(client, IPP_STATUS_ERROR_INTERNAL, "Unable to write print file: %s", strerror(error)); return; } @@ -3768,13 +3672,13 @@ ipp_send_uri(_ipp_client_t *client) /* I - Client */ { int error = errno; /* Write error */ - job->state = IPP_JOB_ABORTED; + job->state = IPP_JSTATE_ABORTED; job->fd = -1; unlink(filename); - respond_ipp(client, IPP_INTERNAL_ERROR, "Unable to write print file: %s", - strerror(error)); + respond_ipp(client, IPP_STATUS_ERROR_INTERNAL, + "Unable to write print file: %s", strerror(error)); return; } @@ -3782,7 +3686,7 @@ ipp_send_uri(_ipp_client_t *client) /* I - Client */ job->fd = -1; job->filename = strdup(filename); - job->state = IPP_JOB_PENDING; + job->state = IPP_JSTATE_PENDING; _cupsRWUnlock(&(client->printer->rwlock)); @@ -3793,8 +3697,8 @@ ipp_send_uri(_ipp_client_t *client) /* I - Client */ #if 0 if (!_cupsThreadCreate((_cups_thread_func_t)process_job, job)) { - job->state = IPP_JOB_ABORTED; - respond_ipp(client, IPP_INTERNAL_ERROR, "Unable to process job."); + job->state = IPP_JSTATE_ABORTED; + respond_ipp(client, IPP_STATUS_ERROR_INTERNAL, "Unable to process job."); return; } @@ -3806,7 +3710,7 @@ ipp_send_uri(_ipp_client_t *client) /* I - Client */ * Return the job info... */ - respond_ipp(client, IPP_OK, NULL); + respond_ipp(client, IPP_STATUS_OK, NULL); ra = cupsArrayNew((cups_array_func_t)strcmp, NULL); cupsArrayAdd(ra, "job-id"); @@ -3827,7 +3731,7 @@ static void ipp_validate_job(_ipp_client_t *client) /* I - Client */ { if (valid_job_attributes(client)) - respond_ipp(client, IPP_OK, NULL); + respond_ipp(client, IPP_STATUS_OK, NULL); } @@ -3842,7 +3746,7 @@ process_client(_ipp_client_t *client) /* I - Client */ * Loop until we are out of requests or timeout (30 seconds)... */ - while (httpWait(&(client->http), 30000)) + while (httpWait(client->http, 30000)) if (!process_http(client)) break; @@ -3863,175 +3767,127 @@ process_client(_ipp_client_t *client) /* I - Client */ int /* O - 1 on success, 0 on failure */ process_http(_ipp_client_t *client) /* I - Client connection */ { - char line[4096], /* Line from client... */ - operation[64], /* Operation code from socket */ - uri[1024], /* URI */ - version[64], /* HTTP version number string */ - *ptr; /* Pointer into strings */ - int major, minor; /* HTTP version numbers */ - http_status_t status; /* Transfer status */ - ipp_state_t state; /* State of IPP transfer */ - - - /* - * Abort if we have an error on the connection... - */ + char uri[1024]; /* URI */ + http_state_t http_state; /* HTTP state */ + http_status_t http_status; /* HTTP status */ + ipp_state_t ipp_state; /* State of IPP transfer */ + char scheme[32], /* Method/scheme */ + userpass[128], /* Username:password */ + hostname[HTTP_MAX_HOST]; + /* Hostname */ + int port; /* Port number */ + const char *encoding; /* Content-Encoding value */ + static const char * const http_states[] = + { /* Strings for logging HTTP method */ + "WAITING", + "OPTIONS", + "GET", + "GET_SEND", + "HEAD", + "POST", + "POST_RECV", + "POST_SEND", + "PUT", + "PUT_RECV", + "DELETE", + "TRACE", + "CONNECT", + "STATUS", + "UNKNOWN_METHOD", + "UNKNOWN_VERSION" + }; - if (client->http.error) - return (0); /* * Clear state variables... */ - httpClearFields(&(client->http)); ippDelete(client->request); ippDelete(client->response); - client->http.activity = time(NULL); - client->http.version = HTTP_1_1; - client->http.keep_alive = HTTP_KEEPALIVE_OFF; - client->http.data_encoding = HTTP_ENCODE_LENGTH; - client->http.data_remaining = 0; - client->request = NULL; - client->response = NULL; - client->operation = HTTP_WAITING; + client->request = NULL; + client->response = NULL; + client->operation = HTTP_STATE_WAITING; /* * Read a request from the connection... */ - while ((ptr = httpGets(line, sizeof(line) - 1, &(client->http))) != NULL) - if (*ptr) - break; - - if (!ptr) - return (0); + while ((http_state = httpReadRequest(client->http, uri, + sizeof(uri))) == HTTP_STATE_WAITING) + usleep(1); /* * Parse the request line... */ - fprintf(stderr, "%s %s\n", client->http.hostname, line); - - switch (sscanf(line, "%63s%1023s%63s", operation, uri, version)) + if (http_state == HTTP_STATE_ERROR) { - case 1 : - fprintf(stderr, "%s Bad request line.\n", client->http.hostname); - respond_http(client, HTTP_BAD_REQUEST, NULL, 0); - return (0); - - case 2 : - client->http.version = HTTP_0_9; - break; - - case 3 : - if (sscanf(version, "HTTP/%d.%d", &major, &minor) != 2) - { - fprintf(stderr, "%s Bad HTTP version.\n", client->http.hostname); - respond_http(client, HTTP_BAD_REQUEST, NULL, 0); - return (0); - } + if (httpError(client->http) == EPIPE) + fprintf(stderr, "%s Client closed connection.\n", client->hostname); + else + fprintf(stderr, "%s Bad request line (%s).\n", client->hostname, + strerror(httpError(client->http))); - if (major < 2) - { - client->http.version = (http_version_t)(major * 100 + minor); - if (client->http.version == HTTP_1_1) - client->http.keep_alive = HTTP_KEEPALIVE_ON; - else - client->http.keep_alive = HTTP_KEEPALIVE_OFF; - } - else - { - respond_http(client, HTTP_NOT_SUPPORTED, NULL, 0); - return (0); - } - break; + return (0); } - - /* - * Handle full URLs in the request line... - */ - - if (!strncmp(client->uri, "http:", 5) || !strncmp(client->uri, "ipp:", 4)) + else if (http_state == HTTP_STATE_UNKNOWN_METHOD) { - char scheme[32], /* Method/scheme */ - userpass[128], /* Username:password */ - hostname[HTTP_MAX_HOST];/* Hostname */ - int port; /* Port number */ - - /* - * Separate the URI into its components... - */ - - if (httpSeparateURI(HTTP_URI_CODING_MOST, uri, scheme, sizeof(scheme), - userpass, sizeof(userpass), - hostname, sizeof(hostname), &port, - client->uri, sizeof(client->uri)) < HTTP_URI_OK) - { - fprintf(stderr, "%s Bad URI \"%s\".\n", client->http.hostname, uri); - respond_http(client, HTTP_BAD_REQUEST, NULL, 0); - return (0); - } + fprintf(stderr, "%s Bad/unknown operation.\n", client->hostname); + respond_http(client, HTTP_STATUS_BAD_REQUEST, NULL, NULL, 0); + return (0); } - else + else if (http_state == HTTP_STATE_UNKNOWN_VERSION) { - /* - * Decode URI - */ - - if (!_httpDecodeURI(client->uri, uri, sizeof(client->uri))) - { - fprintf(stderr, "%s Bad URI \"%s\".\n", client->http.hostname, uri); - respond_http(client, HTTP_BAD_REQUEST, NULL, 0); - return (0); - } + fprintf(stderr, "%s Bad HTTP version.\n", client->hostname); + respond_http(client, HTTP_STATUS_BAD_REQUEST, NULL, NULL, 0); + return (0); } + fprintf(stderr, "%s %s %s\n", client->hostname, http_states[http_state], + uri); + /* - * Process the request... + * Separate the URI into its components... */ - if (!strcmp(operation, "GET")) - client->http.state = HTTP_GET; - else if (!strcmp(operation, "POST")) - client->http.state = HTTP_POST; - else if (!strcmp(operation, "OPTIONS")) - client->http.state = HTTP_OPTIONS; - else if (!strcmp(operation, "HEAD")) - client->http.state = HTTP_HEAD; - else + if (httpSeparateURI(HTTP_URI_CODING_MOST, uri, scheme, sizeof(scheme), + userpass, sizeof(userpass), + hostname, sizeof(hostname), &port, + client->uri, sizeof(client->uri)) < HTTP_URI_STATUS_OK) { - fprintf(stderr, "%s Bad operation \"%s\".\n", client->http.hostname, - operation); - respond_http(client, HTTP_BAD_REQUEST, NULL, 0); + fprintf(stderr, "%s Bad URI \"%s\".\n", client->hostname, uri); + respond_http(client, HTTP_STATUS_BAD_REQUEST, NULL, NULL, 0); return (0); } - client->start = time(NULL); - client->operation = client->http.state; - client->http.status = HTTP_OK; + /* + * Process the request... + */ + + client->start = time(NULL); + client->operation = httpGetState(client->http); /* * Parse incoming parameters until the status changes... */ - while ((status = httpUpdate(&(client->http))) == HTTP_CONTINUE); + while ((http_status = httpUpdate(client->http)) == HTTP_STATUS_CONTINUE); - if (status != HTTP_OK) + if (http_status != HTTP_STATUS_OK) { - respond_http(client, HTTP_BAD_REQUEST, NULL, 0); + respond_http(client, HTTP_STATUS_BAD_REQUEST, NULL, NULL, 0); return (0); } - if (!client->http.fields[HTTP_FIELD_HOST][0] && - client->http.version >= HTTP_1_1) + if (!httpGetField(client->http, HTTP_FIELD_HOST)[0] && + httpGetVersion(client->http) >= HTTP_VERSION_1_1) { /* * HTTP/1.1 and higher require the "Host:" field... */ - respond_http(client, HTTP_BAD_REQUEST, NULL, 0); + respond_http(client, HTTP_STATUS_BAD_REQUEST, NULL, NULL, 0); return (0); } @@ -4039,9 +3895,10 @@ process_http(_ipp_client_t *client) /* I - Client connection */ * Handle HTTP Upgrade... */ - if (!_cups_strcasecmp(client->http.fields[HTTP_FIELD_CONNECTION], "Upgrade")) + if (!_cups_strcasecmp(httpGetField(client->http, HTTP_FIELD_CONNECTION), + "Upgrade")) { - if (!respond_http(client, HTTP_NOT_IMPLEMENTED, NULL, 0)) + if (!respond_http(client, HTTP_STATUS_NOT_IMPLEMENTED, NULL, NULL, 0)) return (0); } @@ -4049,16 +3906,17 @@ process_http(_ipp_client_t *client) /* I - Client connection */ * Handle HTTP Expect... */ - if (client->http.expect && - (client->operation == HTTP_POST || client->operation == HTTP_PUT)) + if (httpGetExpect(client->http) && + (client->operation == HTTP_STATE_POST || + client->operation == HTTP_STATE_PUT)) { - if (client->http.expect == HTTP_CONTINUE) + if (httpGetExpect(client->http) == HTTP_STATUS_CONTINUE) { /* * Send 100-continue header... */ - if (!respond_http(client, HTTP_CONTINUE, NULL, 0)) + if (!respond_http(client, HTTP_STATUS_CONTINUE, NULL, NULL, 0)) return (0); } else @@ -4067,13 +3925,8 @@ process_http(_ipp_client_t *client) /* I - Client connection */ * Send 417-expectation-failed header... */ - if (!respond_http(client, HTTP_EXPECTATION_FAILED, NULL, 0)) + if (!respond_http(client, HTTP_STATUS_EXPECTATION_FAILED, NULL, NULL, 0)) return (0); - - httpPrintf(&(client->http), "Content-Length: 0\r\n"); - httpPrintf(&(client->http), "\r\n"); - httpFlushWrite(&(client->http)); - client->http.data_encoding = HTTP_ENCODE_LENGTH; } } @@ -4081,25 +3934,27 @@ process_http(_ipp_client_t *client) /* I - Client connection */ * Handle new transfers... */ + encoding = httpGetContentEncoding(client->http); + switch (client->operation) { - case HTTP_OPTIONS : + case HTTP_STATE_OPTIONS : /* * Do HEAD/OPTIONS command... */ - return (respond_http(client, HTTP_OK, NULL, 0)); + return (respond_http(client, HTTP_STATUS_OK, NULL, NULL, 0)); - case HTTP_HEAD : + case HTTP_STATE_HEAD : if (!strcmp(client->uri, "/icon.png")) - return (respond_http(client, HTTP_OK, "image/png", 0)); + return (respond_http(client, HTTP_STATUS_OK, NULL, "image/png", 0)); else if (!strcmp(client->uri, "/")) - return (respond_http(client, HTTP_OK, "text/html", 0)); + return (respond_http(client, HTTP_STATUS_OK, NULL, "text/html", 0)); else - return (respond_http(client, HTTP_NOT_FOUND, NULL, 0)); + return (respond_http(client, HTTP_STATUS_NOT_FOUND, NULL, NULL, 0)); break; - case HTTP_GET : + case HTTP_STATE_GET : if (!strcmp(client->uri, "/icon.png")) { /* @@ -4111,24 +3966,27 @@ process_http(_ipp_client_t *client) /* I - Client connection */ char buffer[4096]; /* Copy buffer */ ssize_t bytes; /* Bytes */ + fprintf(stderr, "Icon file is \"%s\".\n", client->printer->icon); + if (!stat(client->printer->icon, &fileinfo) && (fd = open(client->printer->icon, O_RDONLY)) >= 0) { - if (!respond_http(client, HTTP_OK, "image/png", fileinfo.st_size)) + if (!respond_http(client, HTTP_STATUS_OK, NULL, "image/png", + fileinfo.st_size)) { close(fd); return (0); } while ((bytes = read(fd, buffer, sizeof(buffer))) > 0) - httpWrite2(&(client->http), buffer, bytes); + httpWrite2(client->http, buffer, bytes); - httpFlushWrite(&(client->http)); + httpFlushWrite(client->http); close(fd); } else - return (respond_http(client, HTTP_NOT_FOUND, NULL, 0)); + return (respond_http(client, HTTP_STATUS_NOT_FOUND, NULL, NULL, 0)); } else if (!strcmp(client->uri, "/")) { @@ -4136,7 +3994,7 @@ process_http(_ipp_client_t *client) /* I - Client connection */ * Show web status page... */ - if (!respond_http(client, HTTP_OK, "text/html", 0)) + if (!respond_http(client, HTTP_STATUS_OK, encoding, "text/html", 0)) return (0); html_printf(client, @@ -4150,43 +4008,32 @@ process_http(_ipp_client_t *client) /* I - Client connection */ "</head>\n" "<body>\n" "</body>\n" - "<h1>%s</h1>\n" + "<h1><img align=\"right\" src=\"/icon.png\">%s</h1>\n" "<p>%s, %d job(s).</p>\n" "</body>\n" "</html>\n", client->printer->name, client->printer->name, - client->printer->state == IPP_PRINTER_IDLE ? "Idle" : - client->printer->state == IPP_PRINTER_PROCESSING ? + client->printer->state == IPP_PSTATE_IDLE ? "Idle" : + client->printer->state == IPP_PSTATE_PROCESSING ? "Printing" : "Stopped", cupsArrayCount(client->printer->jobs)); - httpWrite2(&(client->http), "", 0); + httpWrite2(client->http, "", 0); return (1); } else - return (respond_http(client, HTTP_NOT_FOUND, NULL, 0)); + return (respond_http(client, HTTP_STATUS_NOT_FOUND, NULL, NULL, 0)); break; - case HTTP_POST : - if (client->http.data_remaining < 0 || - (!client->http.fields[HTTP_FIELD_CONTENT_LENGTH][0] && - client->http.data_encoding == HTTP_ENCODE_LENGTH)) - { - /* - * Negative content lengths are invalid... - */ - - return (respond_http(client, HTTP_BAD_REQUEST, NULL, 0)); - } - - if (strcmp(client->http.fields[HTTP_FIELD_CONTENT_TYPE], + case HTTP_STATE_POST : + if (strcmp(httpGetField(client->http, HTTP_FIELD_CONTENT_TYPE), "application/ipp")) { /* * Not an IPP request... */ - return (respond_http(client, HTTP_BAD_REQUEST, NULL, 0)); + return (respond_http(client, HTTP_STATUS_BAD_REQUEST, NULL, NULL, 0)); } /* @@ -4195,14 +4042,17 @@ process_http(_ipp_client_t *client) /* I - Client connection */ client->request = ippNew(); - while ((state = ippRead(&(client->http), client->request)) != IPP_DATA) - if (state == IPP_ERROR) + while ((ipp_state = ippRead(client->http, + client->request)) != IPP_STATE_DATA) + { + if (ipp_state == IPP_STATE_ERROR) { - fprintf(stderr, "%s IPP read error (%s).\n", client->http.hostname, + fprintf(stderr, "%s IPP read error (%s).\n", client->hostname, cupsLastErrorString()); - respond_http(client, HTTP_BAD_REQUEST, NULL, 0); + respond_http(client, HTTP_STATUS_BAD_REQUEST, NULL, NULL, 0); return (0); } + } /* * Now that we have the IPP request, process the request... @@ -4230,6 +4080,8 @@ process_ipp(_ipp_client_t *client) /* I - Client */ ipp_attribute_t *charset; /* Character set attribute */ ipp_attribute_t *language; /* Language attribute */ ipp_attribute_t *uri; /* Printer URI attribute */ + int major, minor; /* Version number */ + const char *name; /* Name of attribute */ debug_attributes("Request", client->request, 1); @@ -4238,37 +4090,30 @@ process_ipp(_ipp_client_t *client) /* I - Client */ * First build an empty response message for this request... */ - client->operation_id = client->request->request.op.operation_id; - client->response = ippNew(); - - client->response->request.status.version[0] = - client->request->request.op.version[0]; - client->response->request.status.version[1] = - client->request->request.op.version[1]; - client->response->request.status.request_id = - client->request->request.op.request_id; + client->operation_id = ippGetOperation(client->request); + client->response = ippNewResponse(client->request); /* * Then validate the request header and required attributes... */ - if (client->request->request.any.version[0] < 1 || - client->request->request.any.version[0] > 2) + major = ippGetVersion(client->request, &minor); + + if (major < 1 || major > 2) { /* * Return an error, since we only support IPP 1.x and 2.x. */ - respond_ipp(client, IPP_VERSION_NOT_SUPPORTED, - "Bad request version number %d.%d.", - client->request->request.any.version[0], - client->request->request.any.version[1]); + respond_ipp(client, IPP_STATUS_ERROR_VERSION_NOT_SUPPORTED, + "Bad request version number %d.%d.", major, minor); } - else if (client->request->request.any.request_id <= 0) - respond_ipp(client, IPP_BAD_REQUEST, "Bad request-id %d.", - client->request->request.any.request_id); - else if (!client->request->attrs) - respond_ipp(client, IPP_BAD_REQUEST, "No attributes in request."); + else if (ippGetRequestId(client->request) <= 0) + respond_ipp(client, IPP_STATUS_ERROR_BAD_REQUEST, "Bad request-id %d.", + ippGetRequestId(client->request)); + else if (!ippFirstAttribute(client->request)) + respond_ipp(client, IPP_STATUS_ERROR_BAD_REQUEST, + "No attributes in request."); else { /* @@ -4276,22 +4121,25 @@ process_ipp(_ipp_client_t *client) /* I - Client */ * don't repeat groups... */ - for (attr = client->request->attrs, group = attr->group_tag; + for (attr = ippFirstAttribute(client->request), + group = ippGetGroupTag(attr); attr; - attr = attr->next) - if (attr->group_tag < group && attr->group_tag != IPP_TAG_ZERO) + attr = ippNextAttribute(client->request)) + { + if (ippGetGroupTag(attr) < group && ippGetGroupTag(attr) != IPP_TAG_ZERO) { /* * Out of order; return an error... */ - respond_ipp(client, IPP_BAD_REQUEST, - "Attribute groups are out of order (%x < %x).", - attr->group_tag, group); + respond_ipp(client, IPP_STATUS_ERROR_BAD_REQUEST, + "Attribute groups are out of order (%x < %x).", + ippGetGroupTag(attr), group); break; } else - group = attr->group_tag; + group = ippGetGroupTag(attr); + } if (!attr) { @@ -4303,20 +4151,19 @@ process_ipp(_ipp_client_t *client) /* I - Client */ * printer-uri/job-uri */ - attr = client->request->attrs; - if (attr && attr->name && - !strcmp(attr->name, "attributes-charset") && - (attr->value_tag & IPP_TAG_MASK) == IPP_TAG_CHARSET) + attr = ippFirstAttribute(client->request); + name = ippGetName(attr); + if (attr && name && !strcmp(name, "attributes-charset") && + ippGetValueTag(attr) == IPP_TAG_CHARSET) charset = attr; else charset = NULL; - if (attr) - attr = attr->next; + attr = ippNextAttribute(client->request); + name = ippGetName(attr); - if (attr && attr->name && - !strcmp(attr->name, "attributes-natural-language") && - (attr->value_tag & IPP_TAG_MASK) == IPP_TAG_LANGUAGE) + if (attr && name && !strcmp(name, "attributes-natural-language") && + ippGetValueTag(attr) == IPP_TAG_LANGUAGE) language = attr; else language = NULL; @@ -4330,25 +4177,17 @@ process_ipp(_ipp_client_t *client) /* I - Client */ else uri = NULL; - ippAddString(client->response, IPP_TAG_OPERATION, IPP_TAG_CHARSET, - "attributes-charset", NULL, - charset ? charset->values[0].string.text : "utf-8"); - - ippAddString(client->response, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE, - "attributes-natural-language", NULL, - language ? language->values[0].string.text : "en"); - if (charset && - _cups_strcasecmp(charset->values[0].string.text, "us-ascii") && - _cups_strcasecmp(charset->values[0].string.text, "utf-8")) + _cups_strcasecmp(ippGetString(charset, 0, NULL), "us-ascii") && + _cups_strcasecmp(ippGetString(charset, 0, NULL), "utf-8")) { /* * Bad character set... */ - respond_ipp(client, IPP_BAD_REQUEST, + respond_ipp(client, IPP_STATUS_ERROR_BAD_REQUEST, "Unsupported character set \"%s\".", - charset->values[0].string.text); + ippGetString(charset, 0, NULL)); } else if (!charset || !language || !uri) { @@ -4358,14 +4197,15 @@ process_ipp(_ipp_client_t *client) /* I - Client */ * for all operations. */ - respond_ipp(client, IPP_BAD_REQUEST, "Missing required attributes."); + respond_ipp(client, IPP_STATUS_ERROR_BAD_REQUEST, + "Missing required attributes."); } - else if (strcmp(uri->values[0].string.text, client->printer->uri) && - strncmp(uri->values[0].string.text, client->printer->uri, + else if (strcmp(ippGetString(uri, 0, NULL), client->printer->uri) && + strncmp(ippGetString(uri, 0, NULL), client->printer->uri, client->printer->urilen)) { - respond_ipp(client, IPP_NOT_FOUND, "%s %s not found.", uri->name, - uri->values[0].string.text); + respond_ipp(client, IPP_STATUS_ERROR_NOT_FOUND, "%s %s not found.", + ippGetName(uri), ippGetString(uri, 0, NULL)); } else { @@ -4373,60 +4213,62 @@ process_ipp(_ipp_client_t *client) /* I - Client */ * Try processing the operation... */ - if (client->http.expect == HTTP_CONTINUE) +#if 0 /* Already doing this in process_http()... */ + if (httpGetExpect(client->http) == HTTP_STATUS_CONTINUE) { /* * Send 100-continue header... */ - if (!respond_http(client, HTTP_CONTINUE, NULL, 0)) + if (!respond_http(client, HTTP_STATUS_CONTINUE, NULL, NULL, 0)) return (0); } +#endif /* 0 */ - switch (client->request->request.op.operation_id) + switch (ippGetOperation(client->request)) { - case IPP_PRINT_JOB : + case IPP_OP_PRINT_JOB : ipp_print_job(client); break; - case IPP_PRINT_URI : + case IPP_OP_PRINT_URI : ipp_print_uri(client); break; - case IPP_VALIDATE_JOB : + case IPP_OP_VALIDATE_JOB : ipp_validate_job(client); break; - case IPP_CREATE_JOB : + case IPP_OP_CREATE_JOB : ipp_create_job(client); break; - case IPP_SEND_DOCUMENT : + case IPP_OP_SEND_DOCUMENT : ipp_send_document(client); break; - case IPP_SEND_URI : + case IPP_OP_SEND_URI : ipp_send_uri(client); break; - case IPP_CANCEL_JOB : + case IPP_OP_CANCEL_JOB : ipp_cancel_job(client); break; - case IPP_GET_JOB_ATTRIBUTES : + case IPP_OP_GET_JOB_ATTRIBUTES : ipp_get_job_attributes(client); break; - case IPP_GET_JOBS : + case IPP_OP_GET_JOBS : ipp_get_jobs(client); break; - case IPP_GET_PRINTER_ATTRIBUTES : + case IPP_OP_GET_PRINTER_ATTRIBUTES : ipp_get_printer_attributes(client); break; default : - respond_ipp(client, IPP_OPERATION_NOT_SUPPORTED, + respond_ipp(client, IPP_STATUS_ERROR_OPERATION_NOT_SUPPORTED, "Operation not supported."); break; } @@ -4438,10 +4280,10 @@ process_ipp(_ipp_client_t *client) /* I - Client */ * Send the HTTP header and return... */ - if (client->http.state != HTTP_POST_SEND) - httpFlush(&(client->http)); /* Flush trailing (junk) data */ + if (httpGetState(client->http) != HTTP_STATE_POST_SEND) + httpFlush(client->http); /* Flush trailing (junk) data */ - return (respond_http(client, HTTP_OK, "application/ipp", + return (respond_http(client, HTTP_STATUS_OK, NULL, "application/ipp", ippLength(client->response))); } @@ -4453,18 +4295,92 @@ process_ipp(_ipp_client_t *client) /* I - Client */ static void * /* O - Thread exit status */ process_job(_ipp_job_t *job) /* I - Job */ { - job->state = IPP_JOB_PROCESSING; - job->printer->state = IPP_PRINTER_PROCESSING; + job->state = IPP_JSTATE_PROCESSING; + job->printer->state = IPP_PSTATE_PROCESSING; - sleep(5); + if (job->printer->command) + { + /* + * Execute a command with the job spool file and wait for it to complete... + */ + + int pid, /* Process ID */ + status; /* Exit status */ + time_t start, /* Start time */ + end; /* End time */ + + fprintf(stderr, "Running command \"%s %s\".\n", job->printer->command, + job->filename); + time(&start); + + if ((pid = fork()) == 0) + { + /* + * Child comes here... + */ + + execlp(job->printer->command, job->printer->command, job->filename, + (void *)NULL); + exit(errno); + } + else if (pid < 0) + { + /* + * Unable to fork process... + */ + + perror("Unable to start job processing command"); + } + else + { + /* + * Wait for child to complete... + */ + +#ifdef HAVE_WAITPID + while (waitpid(pid, &status, 0) < 0); +#else + while (wait(&status) < 0); +#endif /* HAVE_WAITPID */ + + if (status) + { + if (WIFEXITED(status)) + fprintf(stderr, "Command \"%s\" exited with status %d.\n", + job->printer->command, WEXITSTATUS(status)); + else + fprintf(stderr, "Command \"%s\" terminated with signal %d.\n", + job->printer->command, WTERMSIG(status)); + } + else + fprintf(stderr, "Command \"%s\" completed successfully.\n", + job->printer->command); + } + + /* + * Make sure processing takes at least 5 seconds... + */ + + time(&end); + if ((end - start) < 5) + sleep(5); + } + else + { + /* + * Sleep for a random amount of time to simulate job processing. + */ + + sleep(5 + (rand() % 11)); + } if (job->cancel) - job->state = IPP_JOB_CANCELED; + job->state = IPP_JSTATE_CANCELED; else - job->state = IPP_JOB_COMPLETED; + job->state = IPP_JSTATE_COMPLETED; job->completed = time(NULL); - job->printer->state = IPP_PRINTER_IDLE; + job->printer->state = IPP_PSTATE_IDLE; job->printer->active_job = NULL; return (NULL); @@ -4486,11 +4402,12 @@ register_printer( const char *adminurl, /* I - Web interface URL */ int color, /* I - 1 = color, 0 = monochrome */ int duplex, /* I - 1 = duplex, 0 = simplex */ - const char *regtype) /* I - Service type */ + const char *subtype) /* I - Service subtype */ { DNSServiceErrorType error; /* Error from Bonjour */ char make_model[256],/* Make and model together */ - product[256]; /* Product string */ + product[256], /* Product string */ + regtype[256]; /* Bonjour service type */ /* @@ -4501,16 +4418,14 @@ register_printer( snprintf(product, sizeof(product), "(%s)", model); TXTRecordCreate(&(printer->ipp_txt), 1024, NULL); - TXTRecordSetValue(&(printer->ipp_txt), "txtvers", 1, "1"); - TXTRecordSetValue(&(printer->ipp_txt), "qtotal", 1, "1"); TXTRecordSetValue(&(printer->ipp_txt), "rp", 3, "ipp"); TXTRecordSetValue(&(printer->ipp_txt), "ty", (uint8_t)strlen(make_model), make_model); TXTRecordSetValue(&(printer->ipp_txt), "adminurl", (uint8_t)strlen(adminurl), adminurl); - TXTRecordSetValue(&(printer->ipp_txt), "note", (uint8_t)strlen(location), - location); - TXTRecordSetValue(&(printer->ipp_txt), "priority", 1, "0"); + if (*location) + TXTRecordSetValue(&(printer->ipp_txt), "note", (uint8_t)strlen(location), + location); TXTRecordSetValue(&(printer->ipp_txt), "product", (uint8_t)strlen(product), product); TXTRecordSetValue(&(printer->ipp_txt), "pdl", (uint8_t)strlen(formats), @@ -4521,7 +4436,6 @@ register_printer( make); TXTRecordSetValue(&(printer->ipp_txt), "usb_MDL", (uint8_t)strlen(model), model); - TXTRecordSetValue(&(printer->ipp_txt), "air", 4, "none"); /* * Create a shared service reference for Bonjour... @@ -4562,6 +4476,11 @@ register_printer( printer->ipp_ref = printer->common_ref; + if (subtype && *subtype) + snprintf(regtype, sizeof(regtype), "_ipp._tcp,%s", subtype); + else + strlcpy(regtype, "_ipp._tcp", sizeof(regtype)); + if ((error = DNSServiceRegister(&(printer->ipp_ref), kDNSServiceFlagsShareConnection, 0 /* interfaceIndex */, printer->dnssd_name, @@ -4577,6 +4496,35 @@ register_printer( return (0); } +# ifdef HAVE_SSL + /* + * Then register the _ipps._tcp (IPP) service type with the real port number to + * advertise our IPP printer... + */ + + printer->ipps_ref = printer->common_ref; + + if (subtype && *subtype) + snprintf(regtype, sizeof(regtype), "_ipps._tcp,%s", subtype); + else + strlcpy(regtype, "_ipps._tcp", sizeof(regtype)); + + if ((error = DNSServiceRegister(&(printer->ipps_ref), + kDNSServiceFlagsShareConnection, + 0 /* interfaceIndex */, printer->dnssd_name, + regtype, NULL /* domain */, + NULL /* host */, htons(printer->port), + TXTRecordGetLength(&(printer->ipp_txt)), + TXTRecordGetBytesPtr(&(printer->ipp_txt)), + (DNSServiceRegisterReply)dnssd_callback, + printer)) != kDNSServiceErr_NoError) + { + fprintf(stderr, "Unable to register \"%s.%s\": %d\n", + printer->dnssd_name, regtype, error); + return (0); + } +# endif /* HAVE_SSL */ + /* * Similarly, register the _http._tcp,_printer (HTTP) service type with the * real port number to advertise our IPP printer... @@ -4608,32 +4556,32 @@ register_printer( */ int /* O - 1 on success, 0 on failure */ -respond_http(_ipp_client_t *client, /* I - Client */ - http_status_t code, /* I - HTTP status of response */ - const char *type, /* I - MIME type of response */ - size_t length) /* I - Length of response */ +respond_http( + _ipp_client_t *client, /* I - Client */ + http_status_t code, /* I - HTTP status of response */ + const char *content_encoding, /* I - Content-Encoding of response */ + const char *type, /* I - MIME media type of response */ + size_t length) /* I - Length of response */ { char message[1024]; /* Text message */ - fprintf(stderr, "%s %s\n", client->http.hostname, httpStatus(code)); + fprintf(stderr, "%s %s\n", client->hostname, httpStatus(code)); - if (code == HTTP_CONTINUE) + if (code == HTTP_STATUS_CONTINUE) { /* * 100-continue doesn't send any headers... */ - return (httpPrintf(&(client->http), "HTTP/%d.%d 100 Continue\r\n\r\n", - client->http.version / 100, - client->http.version % 100) > 0); + return (httpWriteResponse(client->http, HTTP_STATUS_CONTINUE) == 0); } /* * Format an error message... */ - if (!type && !length && code != HTTP_OK) + if (!type && !length && code != HTTP_STATUS_OK) { snprintf(message, sizeof(message), "%d - %s\n", code, httpStatus(code)); @@ -4644,60 +4592,30 @@ respond_http(_ipp_client_t *client, /* I - Client */ message[0] = '\0'; /* - * Send the HTTP status header... - */ - - httpFlushWrite(&(client->http)); - - client->http.data_encoding = HTTP_ENCODE_FIELDS; - - if (httpPrintf(&(client->http), "HTTP/%d.%d %d %s\r\n", client->http.version / 100, - client->http.version % 100, code, httpStatus(code)) < 0) - return (0); - - /* - * Follow the header with the response fields... + * Send the HTTP response header... */ - if (httpPrintf(&(client->http), "Date: %s\r\n", httpGetDateString(time(NULL))) < 0) - return (0); - - if (client->http.keep_alive && client->http.version >= HTTP_1_0) - { - if (httpPrintf(&(client->http), - "Connection: Keep-Alive\r\n" - "Keep-Alive: timeout=10\r\n") < 0) - return (0); - } + httpClearFields(client->http); - if (code == HTTP_METHOD_NOT_ALLOWED || client->operation == HTTP_OPTIONS) - { - if (httpPrintf(&(client->http), "Allow: GET, HEAD, OPTIONS, POST\r\n") < 0) - return (0); - } + if (code == HTTP_STATUS_METHOD_NOT_ALLOWED || + client->operation == HTTP_STATE_OPTIONS) + httpSetField(client->http, HTTP_FIELD_ALLOW, "GET, HEAD, OPTIONS, POST"); if (type) { if (!strcmp(type, "text/html")) - { - if (httpPrintf(&(client->http), - "Content-Type: text/html; charset=utf-8\r\n") < 0) - return (0); - } - else if (httpPrintf(&(client->http), "Content-Type: %s\r\n", type) < 0) - return (0); - } + httpSetField(client->http, HTTP_FIELD_CONTENT_TYPE, + "text/html; charset=utf-8"); + else + httpSetField(client->http, HTTP_FIELD_CONTENT_TYPE, type); - if (length == 0 && !message[0]) - { - if (httpPrintf(&(client->http), "Transfer-Encoding: chunked\r\n\r\n") < 0) - return (0); + if (content_encoding) + httpSetField(client->http, HTTP_FIELD_CONTENT_ENCODING, content_encoding); } - else if (httpPrintf(&(client->http), "Content-Length: " CUPS_LLFMT "\r\n\r\n", - CUPS_LLCAST length) < 0) - return (0); - if (httpFlushWrite(&(client->http)) < 0) + httpSetLength(client->http, length); + + if (httpWriteResponse(client->http, code) < 0) return (0); /* @@ -4710,7 +4628,10 @@ respond_http(_ipp_client_t *client, /* I - Client */ * Send a plain text message. */ - if (httpPrintf(&(client->http), "%s", message) < 0) + if (httpPrintf(client->http, "%s", message) < 0) + return (0); + + if (httpWrite2(client->http, "", 0) < 0) return (0); } else if (client->response) @@ -4721,21 +4642,13 @@ respond_http(_ipp_client_t *client, /* I - Client */ debug_attributes("Response", client->response, 2); - client->http.data_encoding = HTTP_ENCODE_LENGTH; - client->http.data_remaining = (off_t)ippLength(client->response); - client->response->state = IPP_IDLE; + ippSetState(client->response, IPP_STATE_IDLE); - if (ippWrite(&(client->http), client->response) != IPP_DATA) + if (ippWrite(client->http, client->response) != IPP_STATE_DATA) return (0); } - else - client->http.data_encoding = HTTP_ENCODE_CHUNKED; - - /* - * Flush the data and return... - */ - return (httpFlushWrite(&(client->http)) >= 0); + return (1); } @@ -4749,36 +4662,35 @@ respond_ipp(_ipp_client_t *client, /* I - Client */ const char *message, /* I - printf-style status-message */ ...) /* I - Additional args as needed */ { - va_list ap; /* Pointer to additional args */ - char formatted[1024]; /* Formatted errror message */ + const char *formatted = NULL; /* Formatted message */ - client->response->request.status.status_code = status; - - if (!client->response->attrs) - { - ippAddString(client->response, IPP_TAG_OPERATION, - IPP_TAG_CHARSET | IPP_TAG_COPY, "attributes-charset", NULL, - "utf-8"); - ippAddString(client->response, IPP_TAG_OPERATION, - IPP_TAG_LANGUAGE | IPP_TAG_COPY, "attributes-natural-language", - NULL, "en-us"); - } + ippSetStatusCode(client->response, status); if (message) { + va_list ap; /* Pointer to additional args */ + ipp_attribute_t *attr; /* New status-message attribute */ + va_start(ap, message); - vsnprintf(formatted, sizeof(formatted), message, ap); + if ((attr = ippFindAttribute(client->response, "status-message", + IPP_TAG_TEXT)) != NULL) + ippSetStringfv(client->response, &attr, 0, message, ap); + else + attr = ippAddStringfv(client->response, IPP_TAG_OPERATION, IPP_TAG_TEXT, + "status-message", NULL, message, ap); va_end(ap); - ippAddString(client->response, IPP_TAG_OPERATION, IPP_TAG_TEXT, - "status-message", NULL, formatted); + formatted = ippGetString(attr, 0, NULL); } - else - formatted[0] = '\0'; - fprintf(stderr, "%s %s %s (%s)\n", client->http.hostname, - ippOpString(client->operation_id), ippErrorString(status), formatted); + if (formatted) + fprintf(stderr, "%s %s %s (%s)\n", client->hostname, + ippOpString(client->operation_id), ippErrorString(status), + formatted); + else + fprintf(stderr, "%s %s %s\n", client->hostname, + ippOpString(client->operation_id), ippErrorString(status)); } @@ -4794,12 +4706,10 @@ respond_unsupported( ipp_attribute_t *temp; /* Copy of attribute */ - if (!client->response->attrs) - respond_ipp(client, IPP_ATTRIBUTES, "Unsupported %s %s%s value.", - attr->name, attr->num_values > 1 ? "1setOf " : "", - ippTagString(attr->value_tag)); - else - ippSetStatusCode(client->response, IPP_ATTRIBUTES); + respond_ipp(client, IPP_STATUS_ERROR_ATTRIBUTES_OR_VALUES, + "Unsupported %s %s%s value.", ippGetName(attr), + ippGetCount(attr) > 1 ? "1setOf " : "", + ippTagString(ippGetValueTag(attr))); temp = ippCopyAttribute(client->response, attr, 0); ippSetGroupTag(client->response, &temp, IPP_TAG_UNSUPPORTED_GROUP); @@ -4900,7 +4810,8 @@ usage(int status) /* O - Exit status */ { if (!status) { - puts(CUPS_SVERSION " - Copyright 2010 by Apple Inc. All rights reserved."); + puts(CUPS_SVERSION " - Copyright 2010-2012 by Apple Inc. All rights " + "reserved."); puts(""); } @@ -4919,7 +4830,7 @@ usage(int status) /* O - Exit status */ puts("-m model Model name (default=Printer)"); puts("-n hostname Hostname for printer"); puts("-p port Port number (default=auto)"); - puts("-r regtype Bonjour service type (default=_ipp._tcp)"); + puts("-r subtype Bonjour service subtype (default=_print)"); puts("-s speed[,color-speed] Speed in pages per minute (default=10,0)"); puts("-v[vvv] Be (very) verbose"); @@ -4939,10 +4850,16 @@ static int /* O - 1 if valid, 0 if not */ valid_doc_attributes( _ipp_client_t *client) /* I - Client */ { - int i; /* Looping var */ + int valid = 1; /* Valid attributes? */ + ipp_op_t op = ippGetOperation(client->request); + /* IPP operation */ + const char *op_name = ippOpString(op); + /* IPP operation name */ ipp_attribute_t *attr, /* Current attribute */ - *supported; /* document-format-supported */ - const char *format = NULL; /* document-format value */ + *supported; /* xxx-supported attribute */ + const char *compression = NULL, + /* compression value */ + *format = NULL; /* document-format value */ /* @@ -4953,17 +4870,31 @@ valid_doc_attributes( IPP_TAG_ZERO)) != NULL) { /* - * If compression is specified, only accept "none"... + * If compression is specified, only accept a supported value in a Print-Job + * or Send-Document request... */ - if (attr->num_values != 1 || attr->value_tag != IPP_TAG_KEYWORD || - strcmp(attr->values[0].string.text, "none")) + compression = ippGetString(attr, 0, NULL); + supported = ippFindAttribute(client->printer->attrs, + "compression-supported", IPP_TAG_KEYWORD); + + if (ippGetCount(attr) != 1 || ippGetValueTag(attr) != IPP_TAG_KEYWORD || + ippGetGroupTag(attr) != IPP_TAG_OPERATION || + (op != IPP_OP_PRINT_JOB && op != IPP_OP_SEND_DOCUMENT && + op != IPP_OP_VALIDATE_JOB) || + !ippContainsString(supported, compression)) + { respond_unsupported(client, attr); + valid = 0; + } else + { fprintf(stderr, "%s %s compression=\"%s\"\n", - client->http.hostname, - ippOpString(client->request->request.op.operation_id), - attr->values[0].string.text); + client->hostname, op_name, compression); + + if (strcmp(compression, "none")) + httpSetField(client->http, HTTP_FIELD_CONTENT_ENCODING, compression); + } } /* @@ -4973,23 +4904,30 @@ valid_doc_attributes( if ((attr = ippFindAttribute(client->request, "document-format", IPP_TAG_ZERO)) != NULL) { - if (attr->num_values != 1 || attr->value_tag != IPP_TAG_MIMETYPE) + if (ippGetCount(attr) != 1 || ippGetValueTag(attr) != IPP_TAG_MIMETYPE || + ippGetGroupTag(attr) != IPP_TAG_OPERATION) + { respond_unsupported(client, attr); + valid = 0; + } else { - format = attr->values[0].string.text; + format = ippGetString(attr, 0, NULL); fprintf(stderr, "%s %s document-format=\"%s\"\n", - client->http.hostname, - ippOpString(client->request->request.op.operation_id), format); + client->hostname, op_name, format); } } else + { format = "application/octet-stream"; + attr = ippAddString(client->request, IPP_TAG_JOB, IPP_TAG_MIMETYPE, + "document-format", NULL, format); + } if (!strcmp(format, "application/octet-stream") && - (client->request->request.op.operation_id == IPP_PRINT_JOB || - client->request->request.op.operation_id == IPP_SEND_DOCUMENT)) + (ippGetOperation(client->request) == IPP_OP_PRINT_JOB || + ippGetOperation(client->request) == IPP_OP_SEND_DOCUMENT)) { /* * Auto-type the file using the first 4 bytes of the file... @@ -4998,7 +4936,7 @@ valid_doc_attributes( unsigned char header[4]; /* First 4 bytes of file */ memset(header, 0, sizeof(header)); - _httpPeek(&(client->http), (char *)header, sizeof(header)); + httpPeek(client->http, (char *)header, sizeof(header)); if (!memcmp(header, "%PDF", 4)) format = "application/pdf"; @@ -5012,35 +4950,26 @@ valid_doc_attributes( if (format) fprintf(stderr, "%s %s Auto-typed document-format=\"%s\"\n", - client->http.hostname, - ippOpString(client->request->request.op.operation_id), format); + client->hostname, op_name, format); if (!attr) attr = ippAddString(client->request, IPP_TAG_JOB, IPP_TAG_MIMETYPE, "document-format", NULL, format); else - { - _cupsStrFree(attr->values[0].string.text); - attr->values[0].string.text = _cupsStrAlloc(format); - } + ippSetString(client->request, &attr, 0, format); } - if (client->request->request.op.operation_id != IPP_CREATE_JOB && + if (op != IPP_OP_CREATE_JOB && (supported = ippFindAttribute(client->printer->attrs, "document-format-supported", - IPP_TAG_MIMETYPE)) != NULL) + IPP_TAG_MIMETYPE)) != NULL && + !ippContainsString(supported, format)) { - for (i = 0; i < supported->num_values; i ++) - if (!_cups_strcasecmp(format, supported->values[i].string.text)) - break; - - if (i >= supported->num_values && attr) - respond_unsupported(client, attr); + respond_unsupported(client, attr); + valid = 0; } - return (!client->response->attrs || - !client->response->attrs->next || - !client->response->attrs->next->next); + return (valid); } @@ -5055,7 +4984,8 @@ static int /* O - 1 if valid, 0 if not */ valid_job_attributes( _ipp_client_t *client) /* I - Client */ { - int i; /* Looping var */ + int i, /* Looping var */ + valid = 1; /* Valid attributes? */ ipp_attribute_t *attr, /* Current attribute */ *supported; /* xxx-supported attribute */ @@ -5064,7 +4994,7 @@ valid_job_attributes( * Check operation attributes... */ - valid_doc_attributes(client); + valid = valid_doc_attributes(client); /* * Check the various job template attributes... @@ -5073,90 +5003,98 @@ valid_job_attributes( if ((attr = ippFindAttribute(client->request, "copies", IPP_TAG_ZERO)) != NULL) { - if (attr->num_values != 1 || attr->value_tag != IPP_TAG_INTEGER || - attr->values[0].integer < 1 || attr->values[0].integer > 999) + if (ippGetCount(attr) != 1 || ippGetValueTag(attr) != IPP_TAG_INTEGER || + ippGetInteger(attr, 0) < 1 || ippGetInteger(attr, 0) > 999) { respond_unsupported(client, attr); + valid = 0; } } if ((attr = ippFindAttribute(client->request, "ipp-attribute-fidelity", IPP_TAG_ZERO)) != NULL) { - if (attr->num_values != 1 || attr->value_tag != IPP_TAG_BOOLEAN) + if (ippGetCount(attr) != 1 || ippGetValueTag(attr) != IPP_TAG_BOOLEAN) { respond_unsupported(client, attr); + valid = 0; } } if ((attr = ippFindAttribute(client->request, "job-hold-until", IPP_TAG_ZERO)) != NULL) { - if (attr->num_values != 1 || - (attr->value_tag != IPP_TAG_NAME && - attr->value_tag != IPP_TAG_NAMELANG && - attr->value_tag != IPP_TAG_KEYWORD) || - strcmp(attr->values[0].string.text, "no-hold")) + if (ippGetCount(attr) != 1 || + (ippGetValueTag(attr) != IPP_TAG_NAME && + ippGetValueTag(attr) != IPP_TAG_NAMELANG && + ippGetValueTag(attr) != IPP_TAG_KEYWORD) || + strcmp(ippGetString(attr, 0, NULL), "no-hold")) { respond_unsupported(client, attr); + valid = 0; } } if ((attr = ippFindAttribute(client->request, "job-name", IPP_TAG_ZERO)) != NULL) { - if (attr->num_values != 1 || - (attr->value_tag != IPP_TAG_NAME && - attr->value_tag != IPP_TAG_NAMELANG)) + if (ippGetCount(attr) != 1 || + (ippGetValueTag(attr) != IPP_TAG_NAME && + ippGetValueTag(attr) != IPP_TAG_NAMELANG)) { respond_unsupported(client, attr); + valid = 0; } } if ((attr = ippFindAttribute(client->request, "job-priority", IPP_TAG_ZERO)) != NULL) { - if (attr->num_values != 1 || attr->value_tag != IPP_TAG_INTEGER || - attr->values[0].integer < 1 || attr->values[0].integer > 100) + if (ippGetCount(attr) != 1 || ippGetValueTag(attr) != IPP_TAG_INTEGER || + ippGetInteger(attr, 0) < 1 || ippGetInteger(attr, 0) > 100) { respond_unsupported(client, attr); + valid = 0; } } if ((attr = ippFindAttribute(client->request, "job-sheets", IPP_TAG_ZERO)) != NULL) { - if (attr->num_values != 1 || - (attr->value_tag != IPP_TAG_NAME && - attr->value_tag != IPP_TAG_NAMELANG && - attr->value_tag != IPP_TAG_KEYWORD) || - strcmp(attr->values[0].string.text, "none")) + if (ippGetCount(attr) != 1 || + (ippGetValueTag(attr) != IPP_TAG_NAME && + ippGetValueTag(attr) != IPP_TAG_NAMELANG && + ippGetValueTag(attr) != IPP_TAG_KEYWORD) || + strcmp(ippGetString(attr, 0, NULL), "none")) { respond_unsupported(client, attr); + valid = 0; } } if ((attr = ippFindAttribute(client->request, "media", IPP_TAG_ZERO)) != NULL) { - if (attr->num_values != 1 || - (attr->value_tag != IPP_TAG_NAME && - attr->value_tag != IPP_TAG_NAMELANG && - attr->value_tag != IPP_TAG_KEYWORD)) + if (ippGetCount(attr) != 1 || + (ippGetValueTag(attr) != IPP_TAG_NAME && + ippGetValueTag(attr) != IPP_TAG_NAMELANG && + ippGetValueTag(attr) != IPP_TAG_KEYWORD)) { respond_unsupported(client, attr); + valid = 0; } else { for (i = 0; i < (int)(sizeof(media_supported) / sizeof(media_supported[0])); i ++) - if (!strcmp(attr->values[0].string.text, media_supported[i])) + if (!strcmp(ippGetString(attr, 0, NULL), media_supported[i])) break; if (i >= (int)(sizeof(media_supported) / sizeof(media_supported[0]))) { respond_unsupported(client, attr); + valid = 0; } } } @@ -5164,9 +5102,11 @@ valid_job_attributes( if ((attr = ippFindAttribute(client->request, "media-col", IPP_TAG_ZERO)) != NULL) { - if (attr->num_values != 1 || attr->value_tag != IPP_TAG_BEGIN_COLLECTION) + if (ippGetCount(attr) != 1 || + ippGetValueTag(attr) != IPP_TAG_BEGIN_COLLECTION) { respond_unsupported(client, attr); + valid = 0; } /* TODO: check for valid media-col */ } @@ -5174,24 +5114,26 @@ valid_job_attributes( if ((attr = ippFindAttribute(client->request, "multiple-document-handling", IPP_TAG_ZERO)) != NULL) { - if (attr->num_values != 1 || attr->value_tag != IPP_TAG_KEYWORD || - (strcmp(attr->values[0].string.text, + if (ippGetCount(attr) != 1 || ippGetValueTag(attr) != IPP_TAG_KEYWORD || + (strcmp(ippGetString(attr, 0, NULL), "separate-documents-uncollated-copies") && - strcmp(attr->values[0].string.text, + strcmp(ippGetString(attr, 0, NULL), "separate-documents-collated-copies"))) { respond_unsupported(client, attr); + valid = 0; } } if ((attr = ippFindAttribute(client->request, "orientation-requested", IPP_TAG_ZERO)) != NULL) { - if (attr->num_values != 1 || attr->value_tag != IPP_TAG_ENUM || - attr->values[0].integer < IPP_PORTRAIT || - attr->values[0].integer > IPP_REVERSE_PORTRAIT) + if (ippGetCount(attr) != 1 || ippGetValueTag(attr) != IPP_TAG_ENUM || + ippGetInteger(attr, 0) < IPP_ORIENT_PORTRAIT || + ippGetInteger(attr, 0) > IPP_ORIENT_REVERSE_PORTRAIT) { respond_unsupported(client, attr); + valid = 0; } } @@ -5199,16 +5141,18 @@ valid_job_attributes( IPP_TAG_ZERO)) != NULL) { respond_unsupported(client, attr); + valid = 0; } if ((attr = ippFindAttribute(client->request, "print-quality", IPP_TAG_ZERO)) != NULL) { - if (attr->num_values != 1 || attr->value_tag != IPP_TAG_ENUM || - attr->values[0].integer < IPP_QUALITY_DRAFT || - attr->values[0].integer > IPP_QUALITY_HIGH) + if (ippGetCount(attr) != 1 || ippGetValueTag(attr) != IPP_TAG_ENUM || + ippGetInteger(attr, 0) < IPP_QUALITY_DRAFT || + ippGetInteger(attr, 0) > IPP_QUALITY_HIGH) { respond_unsupported(client, attr); + valid = 0; } } @@ -5216,41 +5160,45 @@ valid_job_attributes( IPP_TAG_ZERO)) != NULL) { respond_unsupported(client, attr); + valid = 0; } if ((attr = ippFindAttribute(client->request, "sides", IPP_TAG_ZERO)) != NULL) { - if (attr->num_values != 1 || attr->value_tag != IPP_TAG_KEYWORD) + if (ippGetCount(attr) != 1 || ippGetValueTag(attr) != IPP_TAG_KEYWORD) { respond_unsupported(client, attr); + valid = 0; } if ((supported = ippFindAttribute(client->printer->attrs, "sides", IPP_TAG_KEYWORD)) != NULL) { - for (i = 0; i < supported->num_values; i ++) - if (!strcmp(attr->values[0].string.text, - supported->values[i].string.text)) + int count = ippGetCount(supported); + const char *sides = ippGetString(attr, 0, NULL); + + for (i = 0; i < count; i ++) + if (!strcmp(sides, ippGetString(supported, i, NULL))) break; - if (i >= supported->num_values) + if (i >= count) { respond_unsupported(client, attr); + valid = 0; } } else { respond_unsupported(client, attr); + valid = 0; } } - return (!client->response->attrs || - !client->response->attrs->next || - !client->response->attrs->next->next); + return (valid); } /* - * End of "$Id: ippserver.c 10777 2012-12-17 22:18:10Z mike $". + * End of "$Id: ippserver.c 10851 2013-01-31 16:06:14Z mike $". */ |