char *uri, /* I - URI buffer */
size_t urilen) /* I - Size of URI buffer */
{
- (void)http;
- (void)uri;
- (void)urilen;
+ char line[4096], /* HTTP request line */
+ *req_method, /* HTTP request method */
+ *req_uri, /* HTTP request URI */
+ *req_version; /* HTTP request version number string */
- return (HTTP_STATE_ERROR);
+
+ /*
+ * Range check input...
+ */
+
+ if (uri)
+ *uri = '\0';
+
+ if (!http || !uri || urilen < 1 || http->state != HTTP_WAITING)
+ return (HTTP_STATE_ERROR);
+
+ /*
+ * Read a line from the socket...
+ */
+
+ httpClearFields(http);
+
+ if (!httpGets(line, sizeof(line), http))
+ return (HTTP_STATE_ERROR);
+
+ if (!line[0])
+ return (HTTP_WAITING);
+
+ /*
+ * Parse it...
+ */
+
+ req_method = line;
+ req_uri = line;
+
+ while (*req_uri && !isspace(*req_uri & 255))
+ req_uri ++;
+
+ if (!*req_uri)
+ return (HTTP_STATE_ERROR);
+
+ *req_uri++ = '\0';
+
+ while (*req_uri && isspace(*req_uri & 255))
+ req_uri ++;
+
+ req_version = req_uri;
+
+ while (*req_version && !isspace(*req_version & 255))
+ req_version ++;
+
+ if (!*req_version)
+ return (HTTP_STATE_ERROR);
+
+ *req_version++ = '\0';
+
+ while (*req_version && isspace(*req_version & 255))
+ req_version ++;
+
+ /*
+ * Validate...
+ */
+
+ if (!strcmp(req_method, "OPTIONS"))
+ http->state = HTTP_STATE_OPTIONS;
+ else if (!strcmp(req_method, "GET"))
+ http->state = HTTP_STATE_GET;
+ else if (!strcmp(req_method, "HEAD"))
+ http->state = HTTP_STATE_HEAD;
+ else if (!strcmp(req_method, "POST"))
+ http->state = HTTP_STATE_POST;
+ else if (!strcmp(req_method, "PUT"))
+ http->state = HTTP_STATE_PUT;
+ else if (!strcmp(req_method, "DELETE"))
+ http->state = HTTP_STATE_DELETE;
+ else if (!strcmp(req_method, "TRACE"))
+ http->state = HTTP_STATE_TRACE;
+ else if (!strcmp(req_method, "CONNECT"))
+ http->state = HTTP_STATE_CONNECT;
+ else
+ return (HTTP_STATE_UNKNOWN_METHOD);
+
+ if (!strcmp(req_version, "HTTP/1.0"))
+ {
+ http->version = HTTP_VERSION_1_0;
+ http->keep_alive = HTTP_KEEPALIVE_OFF;
+ }
+ else if (!strcmp(req_version, "HTTP/1.1"))
+ {
+ http->version = HTTP_VERSION_1_1;
+ http->keep_alive = HTTP_KEEPALIVE_ON;
+ }
+ else
+ return (HTTP_STATE_UNKNOWN_VERSION);
+
+ strlcpy(uri, req_uri, urilen);
+
+ return (http->state);
}
* @since CUPS 1.7@
*/
-http_state_t /* O - New HTTP connection state */
+int /* O - 0 on success, -1 on error */
httpWriteResponse(http_t *http, /* I - HTTP connection */
http_status_t status) /* I - Status code */
{
- (void)http;
- (void)status;
+ /*
+ * Range check input...
+ */
+
+ if (!http || status < HTTP_CONTINUE)
+ return (-1);
+
+ /*
+ * Set the various standard fields if they aren't already...
+ */
- return (HTTP_STATE_ERROR);
+ if (!http->fields[HTTP_FIELD_DATE][0])
+ httpSetField(http, HTTP_FIELD_DATE, httpGetDateString(time(NULL)));
+
+ if (status >= HTTP_BAD_REQUEST && http->keep_alive)
+ {
+ http->keep_alive = 0;
+ httpSetField(http, HTTP_FIELD_KEEP_ALIVE, "");
+ }
+
+ if (http->version == HTTP_VERSION_1_1)
+ {
+ if (!http->fields[HTTP_FIELD_CONNECTION][0])
+ {
+ if (http->keep_alive)
+ httpSetField(http, HTTP_FIELD_CONNECTION, "Keep-Alive");
+ else
+ httpSetField(http, HTTP_FIELD_CONNECTION, "close");
+ }
+
+ if (http->keep_alive && !http->fields[HTTP_FIELD_KEEP_ALIVE][0])
+ httpSetField(http, HTTP_FIELD_KEEP_ALIVE, "timeout=10");
+ }
+
+#ifdef HAVE_SSL
+ if (status == HTTP_UPGRADE_REQUIRED)
+ {
+ if (!http->fields[HTTP_FIELD_CONNECTION][0])
+ httpSetField(http, HTTP_FIELD_CONNECTION, "Upgrade");
+
+ if (!http->fields[HTTP_FIELD_UPGRADE][0])
+ httpSetField(http, HTTP_FIELD_UPGRADE, "TLS/1.2,TLS/1.1,TLS/1.0");
+ }
+#endif /* HAVE_SSL */
+
+ if (!http->server)
+ httpSetField(http, HTTP_FIELD_SERVER, CUPS_MINIMAL);
+
+ /*
+ * Send the response header...
+ */
+
+ http->data_encoding = HTTP_ENCODING_FIELDS;
+
+ if (httpPrintf(http, "HTTP/%d.%d %d %s\r\n", http->version / 100,
+ http->version % 100, (int)status, httpStatus(status)) < 0)
+ {
+ http->status = HTTP_STATUS_ERROR;
+ http->data_encoding = HTTP_ENCODING_LENGTH;
+ return (-1);
+ }
+
+ if (status != HTTP_CONTINUE)
+ {
+ /*
+ * 100 Continue doesn't have the rest of the response headers...
+ */
+
+ int i; /* Looping var */
+ const char *value; /* Field value */
+
+ for (i = 0; i < HTTP_FIELD_MAX; i ++)
+ {
+ if ((value = httpGetField(http, i)) != NULL && *value)
+ {
+ if (httpPrintf(http, "%s: %s\r\n", http_fields[i], value) < 1)
+ {
+ http->status = HTTP_STATUS_ERROR;
+ http->data_encoding = HTTP_ENCODING_LENGTH;
+ return (-1);
+ }
+ }
+ }
+
+ if (http->cookie)
+ {
+ if (httpPrintf(http, "Set-Cookie: %s path=/%s\r\n", http->cookie,
+ http->tls ? " secure" : "") < 1)
+ {
+ http->status = HTTP_ERROR;
+ http->data_encoding = HTTP_ENCODING_LENGTH;
+ return (-1);
+ }
+ }
+ }
+
+ if (httpWrite2(http, "\r\n", 2) < 2)
+ {
+ http->status = HTTP_ERROR;
+ http->data_encoding = HTTP_ENCODING_LENGTH;
+ return (-1);
+ }
+
+ if (httpFlushWrite(http) < 0)
+ {
+ http->status = HTTP_ERROR;
+ http->data_encoding = HTTP_ENCODING_LENGTH;
+ return (-1);
+ }
+
+ (void)httpGetLength2(http);
+
+ http_content_coding_start(http,
+ httpGetField(http, HTTP_FIELD_CONTENT_ENCODING));
+
+ return (0);
}
* 'http_send()' - Send a request with all fields and the trailing blank line.
*/
-static int /* O - 0 on success, non-zero on error */
-http_send(http_t *http, /* I - Connection to server */
- http_state_t request, /* I - Request code */
- const char *uri) /* I - URI */
+static int /* O - 0 on success, non-zero on error */
+http_send(http_t *http, /* I - Connection to server */
+ http_state_t request, /* I - Request code */
+ const char *uri) /* I - URI */
{
- int i; /* Looping var */
- char buf[1024]; /* Encoded URI buffer */
- const char *value; /* Field value */
- static const char * const codes[] =
- { /* Request code strings */
+ int i; /* Looping var */
+ char buf[1024]; /* Encoded URI buffer */
+ const char *value; /* Field value */
+ static const char * const codes[] = /* Request code strings */
+ {
NULL,
"OPTIONS",
"GET",
typedef enum http_encoding_e /**** HTTP transfer encoding values ****/
{
- HTTP_ENCODE_LENGTH, /* Data is sent with Content-Length */
- HTTP_ENCODE_CHUNKED, /* Data is chunked */
- HTTP_ENCODE_FIELDS /* Sending HTTP fields */
+ HTTP_ENCODING_LENGTH, /* Data is sent with Content-Length */
+ HTTP_ENCODING_CHUNKED, /* Data is chunked */
+ HTTP_ENCODING_FIELDS /* Sending HTTP fields */
+
+# ifndef CUPS_NO_DEPRECATED
+# define HTTP_ENCODE_LENGTH HTTP_ENCODING_LENGTH
+# define HTTP_ENCODE_CHUNKED HTTP_ENCODING_CHUNKED
+# define HTTP_ENCODE_FIELDS HTTP_ENCODING_FIELDS
+# endif /* !CUPS_NO_DEPRECATED */
} http_encoding_t;
typedef enum http_encryption_e /**** HTTP encryption values ****/
{
- HTTP_ENCRYPT_IF_REQUESTED, /* Encrypt if requested (TLS upgrade) */
- HTTP_ENCRYPT_NEVER, /* Never encrypt */
- HTTP_ENCRYPT_REQUIRED, /* Encryption is required (TLS upgrade) */
- HTTP_ENCRYPT_ALWAYS /* Always encrypt (SSL) */
+ HTTP_ENCRYPTION_IF_REQUESTED, /* Encrypt if requested (TLS upgrade) */
+ HTTP_ENCRYPTION_NEVER, /* Never encrypt */
+ HTTP_ENCRYPTION_REQUIRED, /* Encryption is required (TLS upgrade) */
+ HTTP_ENCRYPTION_ALWAYS /* Always encrypt (SSL) */
+
+# ifndef CUPS_NO_DEPRECATED
+# define HTTP_ENCRYPT_IF_REQUESTED HTTP_ENCRYPTION_IF_REQUESTED
+# define HTTP_ENCRYPT_NEVER HTTP_ENCRYPTION_NEVER
+# define HTTP_ENCRYPT_REQUIRED HTTP_ENCRYPTION_REQUIRED
+# define HTTP_ENCRYPT_ALWAYS HTTP_ENCRYPTION_ALWAYS
+# endif /* !CUPS_NO_DEPRECATED */
} http_encryption_t;
typedef enum http_field_e /**** HTTP field names ****/
****/
{
HTTP_STATE_ERROR = -1, /* Error on socket */
- HTTP_WAITING, /* Waiting for command */
- HTTP_OPTIONS, /* OPTIONS command, waiting for blank line */
- HTTP_GET, /* GET command, waiting for blank line */
- HTTP_GET_SEND, /* GET command, sending data */
- HTTP_HEAD, /* HEAD command, waiting for blank line */
- HTTP_POST, /* POST command, waiting for blank line */
- HTTP_POST_RECV, /* POST command, receiving data */
- HTTP_POST_SEND, /* POST command, sending data */
- HTTP_PUT, /* PUT command, waiting for blank line */
- HTTP_PUT_RECV, /* PUT command, receiving data */
- HTTP_DELETE, /* DELETE command, waiting for blank line */
- HTTP_TRACE, /* TRACE command, waiting for blank line */
- HTTP_CLOSE, /* CLOSE command, waiting for blank line */
- HTTP_STATUS, /* Command complete, sending status */
- HTTP_STATE_UNKNOWN /* Unknown request method, waiting for blank line */
+ HTTP_STATE_WAITING, /* Waiting for command */
+ HTTP_STATE_OPTIONS, /* OPTIONS command, waiting for blank line */
+ HTTP_STATE_GET, /* GET command, waiting for blank line */
+ HTTP_STATE_GET_SEND, /* GET command, sending data */
+ HTTP_STATE_HEAD, /* HEAD command, waiting for blank line */
+ HTTP_STATE_POST, /* POST command, waiting for blank line */
+ HTTP_STATE_POST_RECV, /* POST command, receiving data */
+ HTTP_STATE_POST_SEND, /* POST command, sending data */
+ HTTP_STATE_PUT, /* PUT command, waiting for blank line */
+ HTTP_STATE_PUT_RECV, /* PUT command, receiving data */
+ HTTP_STATE_DELETE, /* DELETE command, waiting for blank line */
+ HTTP_STATE_TRACE, /* TRACE command, waiting for blank line */
+ HTTP_STATE_CONNECT, /* CONNECT command, waiting for blank line */
+ HTTP_STATE_STATUS, /* Command complete, sending status */
+ HTTP_STATE_UNKNOWN_METHOD, /* Unknown request method, waiting for blank line */
+ HTTP_STATE_UNKNOWN_VERSION /* Unknown request method, waiting for blank line */
+
+# ifndef CUPS_NO_DEPRECATED
+/* Old names for this enumeration */
+# define HTTP_WAITING HTTP_STATE_WAITING
+# define HTTP_OPTIONS HTTP_STATE_OPTIONS
+# define HTTP_GET HTTP_STATE_GET
+# define HTTP_GET_SEND HTTP_STATE_GET_SEND
+# define HTTP_HEAD HTTP_STATE_HEAD
+# define HTTP_POST HTTP_STATE_POST
+# define HTTP_POST_RECV HTTP_STATE_POST_RECV
+# define HTTP_POST_SEND HTTP_STATE_POST_SEND
+# define HTTP_PUT HTTP_STATE_PUT
+# define HTTP_PUT_RECV HTTP_STATE_PUT_RECV
+# define HTTP_DELETE HTTP_STATE_DELETE
+# define HTTP_TRACE HTTP_STATE_TRACE
+# define HTTP_CLOSE HTTP_STATE_CONNECT
+# define HTTP_STATUS HTTP_STATE_STATUS
+# endif /* !CUPS_NO_DEPRECATED */
} http_state_t;
typedef enum http_status_e /**** HTTP status codes ****/
{
- HTTP_ERROR = -1, /* An error response from httpXxxx() */
-
- HTTP_CONTINUE = 100, /* Everything OK, keep going... */
- HTTP_SWITCHING_PROTOCOLS, /* HTTP upgrade to TLS/SSL */
-
- HTTP_OK = 200, /* OPTIONS/GET/HEAD/POST/TRACE command was successful */
- HTTP_CREATED, /* PUT command was successful */
- HTTP_ACCEPTED, /* DELETE command was successful */
- HTTP_NOT_AUTHORITATIVE, /* Information isn't authoritative */
- HTTP_NO_CONTENT, /* Successful command, no new data */
- HTTP_RESET_CONTENT, /* Content was reset/recreated */
- HTTP_PARTIAL_CONTENT, /* Only a partial file was recieved/sent */
-
- HTTP_MULTIPLE_CHOICES = 300, /* Multiple files match request */
- HTTP_MOVED_PERMANENTLY, /* Document has moved permanently */
- HTTP_MOVED_TEMPORARILY, /* Document has moved temporarily */
- HTTP_SEE_OTHER, /* See this other link... */
- HTTP_NOT_MODIFIED, /* File not modified */
- HTTP_USE_PROXY, /* Must use a proxy to access this URI */
-
- HTTP_BAD_REQUEST = 400, /* Bad request */
- HTTP_UNAUTHORIZED, /* Unauthorized to access host */
- HTTP_PAYMENT_REQUIRED, /* Payment required */
- HTTP_FORBIDDEN, /* Forbidden to access this URI */
- HTTP_NOT_FOUND, /* URI was not found */
- HTTP_METHOD_NOT_ALLOWED, /* Method is not allowed */
- HTTP_NOT_ACCEPTABLE, /* Not Acceptable */
- HTTP_PROXY_AUTHENTICATION, /* Proxy Authentication is Required */
- HTTP_REQUEST_TIMEOUT, /* Request timed out */
- HTTP_CONFLICT, /* Request is self-conflicting */
- HTTP_GONE, /* Server has gone away */
- HTTP_LENGTH_REQUIRED, /* A content length or encoding is required */
- HTTP_PRECONDITION, /* Precondition failed */
- HTTP_REQUEST_TOO_LARGE, /* Request entity too large */
- HTTP_URI_TOO_LONG, /* URI too long */
- HTTP_UNSUPPORTED_MEDIATYPE, /* The requested media type is unsupported */
- HTTP_REQUESTED_RANGE, /* The requested range is not satisfiable */
- HTTP_EXPECTATION_FAILED, /* The expectation given in an Expect header field was not met */
- HTTP_UPGRADE_REQUIRED = 426, /* Upgrade to SSL/TLS required */
-
- HTTP_SERVER_ERROR = 500, /* Internal server error */
- HTTP_NOT_IMPLEMENTED, /* Feature not implemented */
- HTTP_BAD_GATEWAY, /* Bad gateway */
- HTTP_SERVICE_UNAVAILABLE, /* Service is unavailable */
- HTTP_GATEWAY_TIMEOUT, /* Gateway connection timed out */
- HTTP_NOT_SUPPORTED, /* HTTP version not supported */
-
- HTTP_AUTHORIZATION_CANCELED = 1000, /* User canceled authorization @since CUPS 1.4@ */
- HTTP_PKI_ERROR, /* Error negotiating a secure connection @since CUPS 1.5/OS X 10.7@ */
- HTTP_WEBIF_DISABLED /* Web interface is disabled @private@ */
+ HTTP_STATUS_ERROR = -1, /* An error response from httpXxxx() */
+
+ HTTP_STATUS_CONTINUE = 100, /* Everything OK, keep going... */
+ HTTP_STATUS_SWITCHING_PROTOCOLS, /* HTTP upgrade to TLS/SSL */
+
+ HTTP_STATUS_OK = 200, /* OPTIONS/GET/HEAD/POST/TRACE command was successful */
+ HTTP_STATUS_CREATED, /* PUT command was successful */
+ HTTP_STATUS_ACCEPTED, /* DELETE command was successful */
+ HTTP_STATUS_NOT_AUTHORITATIVE, /* Information isn't authoritative */
+ HTTP_STATUS_NO_CONTENT, /* Successful command, no new data */
+ HTTP_STATUS_RESET_CONTENT, /* Content was reset/recreated */
+ HTTP_STATUS_PARTIAL_CONTENT, /* Only a partial file was recieved/sent */
+
+ HTTP_STATUS_MULTIPLE_CHOICES = 300, /* Multiple files match request */
+ HTTP_STATUS_MOVED_PERMANENTLY, /* Document has moved permanently */
+ HTTP_STATUS_MOVED_TEMPORARILY, /* Document has moved temporarily */
+ HTTP_STATUS_SEE_OTHER, /* See this other link... */
+ HTTP_STATUS_NOT_MODIFIED, /* File not modified */
+ HTTP_STATUS_USE_PROXY, /* Must use a proxy to access this URI */
+
+ HTTP_STATUS_BAD_REQUEST = 400, /* Bad request */
+ HTTP_STATUS_UNAUTHORIZED, /* Unauthorized to access host */
+ HTTP_STATUS_PAYMENT_REQUIRED, /* Payment required */
+ HTTP_STATUS_FORBIDDEN, /* Forbidden to access this URI */
+ HTTP_STATUS_NOT_FOUND, /* URI was not found */
+ HTTP_STATUS_METHOD_NOT_ALLOWED, /* Method is not allowed */
+ HTTP_STATUS_NOT_ACCEPTABLE, /* Not Acceptable */
+ HTTP_STATUS_PROXY_AUTHENTICATION, /* Proxy Authentication is Required */
+ HTTP_STATUS_REQUEST_TIMEOUT, /* Request timed out */
+ HTTP_STATUS_CONFLICT, /* Request is self-conflicting */
+ HTTP_STATUS_GONE, /* Server has gone away */
+ HTTP_STATUS_LENGTH_REQUIRED, /* A content length or encoding is required */
+ HTTP_STATUS_PRECONDITION, /* Precondition failed */
+ HTTP_STATUS_REQUEST_TOO_LARGE, /* Request entity too large */
+ HTTP_STATUS_URI_TOO_LONG, /* URI too long */
+ HTTP_STATUS_UNSUPPORTED_MEDIATYPE, /* The requested media type is unsupported */
+ HTTP_STATUS_REQUESTED_RANGE, /* The requested range is not satisfiable */
+ HTTP_STATUS_EXPECTATION_FAILED, /* The expectation given in an Expect header field was not met */
+ HTTP_STATUS_UPGRADE_REQUIRED = 426, /* Upgrade to SSL/TLS required */
+
+ HTTP_STATUS_SERVER_ERROR = 500, /* Internal server error */
+ HTTP_STATUS_NOT_IMPLEMENTED, /* Feature not implemented */
+ HTTP_STATUS_BAD_GATEWAY, /* Bad gateway */
+ HTTP_STATUS_SERVICE_UNAVAILABLE, /* Service is unavailable */
+ HTTP_STATUS_GATEWAY_TIMEOUT, /* Gateway connection timed out */
+ HTTP_STATUS_NOT_SUPPORTED, /* HTTP version not supported */
+
+ CUPS_STATUS_AUTHORIZATION_CANCELED = 1000,
+ /* User canceled authorization @since CUPS 1.4@ */
+ CUPS_STATUS_PKI_ERROR, /* Error negotiating a secure connection @since CUPS 1.5/OS X 10.7@ */
+ CUPS_STATUS_WEBIF_DISABLED /* Web interface is disabled @private@ */
+
+# ifndef CUPS_NO_DEPRECATED
+/* Old names for this enumeration */
+# define HTTP_ERROR HTTP_STATUS_ERROR
+
+# define HTTP_CONTINUE HTTP_STATUS_CONTINUE
+# define HTTP_SWITCHING_PROTOCOLS HTTP_STATUS_SWITCHING_PROTOCOLS
+
+# define HTTP_OK HTTP_STATUS_OK
+# define HTTP_CREATED HTTP_STATUS_CREATED
+# define HTTP_ACCEPTED HTTP_STATUS_ACCEPTED
+# define HTTP_NOT_AUTHORITATIVE HTTP_STATUS_NOT_AUTHORITATIVE
+# define HTTP_NO_CONTENT HTTP_STATUS_NO_CONTENT
+# define HTTP_RESET_CONTENT HTTP_STATUS_RESET_CONTENT
+# define HTTP_PARTIAL_CONTENT HTTP_STATUS_PARTIAL_CONTENT
+
+# define HTTP_MULTIPLE_CHOICES HTTP_STATUS_MULTIPLE_CHOICES
+# define HTTP_MOVED_PERMANENTLY HTTP_STATUS_MOVED_PERMANENTLY
+# define HTTP_MOVED_TEMPORARILY HTTP_STATUS_MOVED_TEMPORARILY
+# define HTTP_SEE_OTHER HTTP_STATUS_SEE_OTHER
+# define HTTP_NOT_MODIFIED HTTP_STATUS_NOT_MODIFIED
+# define HTTP_USE_PROXY HTTP_STATUS_USE_PROXY
+
+# define HTTP_BAD_REQUEST HTTP_STATUS_BAD_REQUEST
+# define HTTP_UNAUTHORIZED HTTP_STATUS_UNAUTHORIZED
+# define HTTP_PAYMENT_REQUIRED HTTP_STATUS_PAYMENT_REQUIRED
+# define HTTP_FORBIDDEN HTTP_STATUS_FORBIDDEN
+# define HTTP_NOT_FOUND HTTP_STATUS_NOT_FOUND
+# define HTTP_METHOD_NOT_ALLOWED HTTP_STATUS_METHOD_NOT_ALLOWED
+# define HTTP_NOT_ACCEPTABLE HTTP_STATUS_NOT_ACCEPTABLE
+# define HTTP_PROXY_AUTHENTICATION HTTP_STATUS_PROXY_AUTHENTICATION
+# define HTTP_REQUEST_TIMEOUT HTTP_STATUS_REQUEST_TIMEOUT
+# define HTTP_CONFLICT HTTP_STATUS_CONFLICT
+# define HTTP_GONE HTTP_STATUS_GONE
+# define HTTP_LENGTH_REQUIRED HTTP_STATUS_LENGTH_REQUIRED
+# define HTTP_PRECONDITION HTTP_STATUS_PRECONDITION
+# define HTTP_REQUEST_TOO_LARGE HTTP_STATUS_REQUEST_TOO_LARGE
+# define HTTP_URI_TOO_LONG HTTP_STATUS_URI_TOO_LONG
+# define HTTP_UNSUPPORTED_MEDIATYPE HTTP_STATUS_UNSUPPORTED_MEDIATYPE
+# define HTTP_REQUESTED_RANGE HTTP_STATUS_REQUESTED_RANGE
+# define HTTP_EXPECTATION_FAILED HTTP_STATUS_EXPECTATION_FAILED
+# define HTTP_UPGRADE_REQUIRED HTTP_STATUS_UPGRADE_REQUIRED
+
+# define HTTP_SERVER_ERROR HTTP_STATUS_SERVER_ERROR
+# define HTTP_NOT_IMPLEMENTED HTTP_STATUS_NOT_IMPLEMENTED
+# define HTTP_BAD_GATEWAY HTTP_STATUS_BAD_GATEWAY
+# define HTTP_SERVICE_UNAVAILABLE HTTP_STATUS_SERVICE_UNAVAILABLE
+# define HTTP_GATEWAY_TIMEOUT HTTP_STATUS_GATEWAY_TIMEOUT
+# define HTTP_NOT_SUPPORTED HTTP_STATUS_NOT_SUPPORTED
+
+# define HTTP_AUTHORIZATION_CANCELED CUPS_STATUS_AUTHORIZATION_CANCELED
+# define HTTP_PKI_ERROR CUPS_STATUS_PKI_ERROR
+# define HTTP_WEBIF_DISABLED CUPS_STATUS_WEBIF_DISABLED
+# endif /* !CUPS_NO_DEPRECATED */
} http_status_t;
typedef enum http_uri_status_e /**** URI separation status @since CUPS 1.2@ ****/
{
- HTTP_URI_OVERFLOW = -8, /* URI buffer for httpAssembleURI is too small */
- HTTP_URI_BAD_ARGUMENTS = -7, /* Bad arguments to function (error) */
- HTTP_URI_BAD_RESOURCE = -6, /* Bad resource in URI (error) */
- HTTP_URI_BAD_PORT = -5, /* Bad port number in URI (error) */
- HTTP_URI_BAD_HOSTNAME = -4, /* Bad hostname in URI (error) */
- HTTP_URI_BAD_USERNAME = -3, /* Bad username in URI (error) */
- HTTP_URI_BAD_SCHEME = -2, /* Bad scheme in URI (error) */
- HTTP_URI_BAD_URI = -1, /* Bad/empty URI (error) */
- HTTP_URI_OK = 0, /* URI decoded OK */
- HTTP_URI_MISSING_SCHEME, /* Missing scheme in URI (warning) */
- HTTP_URI_UNKNOWN_SCHEME, /* Unknown scheme in URI (warning) */
- HTTP_URI_MISSING_RESOURCE /* Missing resource in URI (warning) */
+ HTTP_URI_STATUS_OVERFLOW = -8, /* URI buffer for httpAssembleURI is too small */
+ HTTP_URI_STATUS_BAD_ARGUMENTS = -7, /* Bad arguments to function (error) */
+ HTTP_URI_STATUS_BAD_RESOURCE = -6, /* Bad resource in URI (error) */
+ HTTP_URI_STATUS_BAD_PORT = -5, /* Bad port number in URI (error) */
+ HTTP_URI_STATUS_BAD_HOSTNAME = -4, /* Bad hostname in URI (error) */
+ HTTP_URI_STATUS_BAD_USERNAME = -3, /* Bad username in URI (error) */
+ HTTP_URI_STATUS_BAD_SCHEME = -2, /* Bad scheme in URI (error) */
+ HTTP_URI_STATUS_BAD_URI = -1, /* Bad/empty URI (error) */
+ HTTP_URI_STATUS_OK = 0, /* URI decoded OK */
+ HTTP_URI_STATUS_MISSING_SCHEME, /* Missing scheme in URI (warning) */
+ HTTP_URI_STATUS_UNKNOWN_SCHEME, /* Unknown scheme in URI (warning) */
+ HTTP_URI_STATUS_MISSING_RESOURCE /* Missing resource in URI (warning) */
+
+# ifndef CUPS_NO_DEPRECATED
+# define HTTP_URI_OVERFLOW HTTP_URI_STATUS_OVERFLOW
+# define HTTP_URI_BAD_ARGUMENTS HTTP_URI_STATUS_BAD_ARGUMENTS
+# define HTTP_URI_BAD_RESOURCE HTTP_URI_STATUS_BAD_RESOURCE
+# define HTTP_URI_BAD_PORT HTTP_URI_STATUS_BAD_PORT
+# define HTTP_URI_BAD_HOSTNAME HTTP_URI_STATUS_BAD_HOSTNAME
+# define HTTP_URI_BAD_USERNAME HTTP_URI_STATUS_BAD_USERNAME
+# define HTTP_URI_BAD_SCHEME HTTP_URI_STATUS_BAD_SCHEME
+# define HTTP_URI_BAD_URI HTTP_URI_STATUS_BAD_URI
+# define HTTP_URI_OK HTTP_URI_STATUS_OK
+# define HTTP_URI_MISSING_SCHEME HTTP_URI_STATUS_MISSING_SCHEME
+# define HTTP_URI_UNKNOWN_SCHEME HTTP_URI_STATUS_UNKNOWN_SCHEME
+# define HTTP_URI_MISSING_RESOURCE HTTP_URI_STATUS_MISSING_RESOURCE
+# endif /* !CUPS_NO_DEPRECATED */
} http_uri_status_t;
typedef enum http_uri_coding_e /**** URI en/decode flags ****/
typedef enum http_version_e /**** HTTP version numbers ****/
{
- HTTP_0_9 = 9, /* HTTP/0.9 */
- HTTP_1_0 = 100, /* HTTP/1.0 */
- HTTP_1_1 = 101 /* HTTP/1.1 */
+ HTTP_VERSION_0_9 = 9, /* HTTP/0.9 */
+ HTTP_VERSION_1_0 = 100, /* HTTP/1.0 */
+ HTTP_VERSION_1_1 = 101 /* HTTP/1.1 */
+
+# ifndef CUPS_NO_DEPRECATED
+# define HTTP_0_9 HTTP_VERSION_0_9
+# define HTTP_1_0 HTTP_VERSION_1_0
+# define HTTP_1_1 HTTP_VERSION_1_1
+# endif /* !CUPS_NO_DEPRECATED */
} http_version_t;
typedef union _http_addr_u /**** Socket address union, which
* ippAddResolutions() - Add resolution values to an IPP message.
* ippAddSeparator() - Add a group separator to an IPP message.
* ippAddString() - Add a language-encoded string to an IPP message.
+ * ippAddStringf() - Add a formatted string to an IPP message.
+ * ippAddStringfv() - Add a formatted string to an IPP message.
* ippAddStrings() - Add language-encoded strings to an IPP message.
* ippCopyAttribute() - Copy an attribute.
* ippCopyAttributes() - Copy attributes from one IPP message to another.
* ippGetBoolean() - Get a boolean value for an attribute.
* ippGetCollection() - Get a collection value for an attribute.
* ippGetCount() - Get the number of values in an attribute.
- * ippGetDate() - Get a date value for an attribute.
+ * ippGetDate() - Get a date value for an attribute.
* ippGetGroupTag() - Get the group associated with an attribute.
* ippGetInteger() - Get the integer/enum value for an attribute.
* ippGetName() - Get the attribute name.
* ippGetOperation() - Get the operation ID in an IPP message.
- * ippGetRange() - Get a rangeOfInteger value from an attribute.
+ * ippGetRange() - Get a rangeOfInteger value from an attribute.
* ippGetRequestId() - Get the request ID from an IPP message.
* ippGetResolution() - Get a resolution value for an attribute.
+ * ippGetState() - Get the IPP message state.
* ippGetStatusCode() - Get the status code from an IPP response or event
* message.
* ippGetString() - Get the string and optionally the language code
* ippNextAttribute() - Return the next attribute in the message.
* ippNew() - Allocate a new IPP message.
* ippNewRequest() - Allocate a new IPP request message.
+ * ippNewResponse() - Allocate a new IPP response message.
* ippRead() - Read data for an IPP message from a HTTP
* connection.
* ippReadFile() - Read data for an IPP message from a file.
* ippReadIO() - Read data for an IPP message.
* ippSetBoolean() - Set a boolean value in an attribute.
* ippSetCollection() - Set a collection value in an attribute.
- * ippSetDate() - Set a date value in an attribute.
+ * ippSetDate() - Set a date value in an attribute.
* ippSetGroupTag() - Set the group tag of an attribute.
* ippSetInteger() - Set an integer or enum value in an attribute.
* ippSetName() - Set the name of an attribute.
* ippSetRange() - Set a rangeOfInteger value in an attribute.
* ippSetRequestId() - Set the request ID in an IPP message.
* ippSetResolution() - Set a resolution value in an attribute.
- * ippSetState() - Set the current state of the IPP message.
+ * ippSetState() - Set the current state of the IPP message.
* ippSetStatusCode() - Set the status code in an IPP response or event
* message.
* ippSetString() - Set a string value in an attribute.
/*
* 'ippAddBoolean()' - Add a boolean attribute to an IPP message.
*
- * The @code ipp@ parameter refers to an IPP message previously created using the
- * @link ippNew@ or @link ippNewRequest@ functions.
+ * The @code ipp@ parameter refers to an IPP message previously created using
+ * the @link ippNew@, @link ippNewRequest@, or @link ippNewResponse@ functions.
*
* The @code group@ parameter specifies the IPP attribute group tag: none
* (@code IPP_TAG_ZERO@, for member attributes), document (@code IPP_TAG_DOCUMENT@),
/*
* 'ippAddBooleans()' - Add an array of boolean values.
*
- * The @code ipp@ parameter refers to an IPP message previously created using the
- * @link ippNew@ or @link ippNewRequest@ functions.
+ * The @code ipp@ parameter refers to an IPP message previously created using
+ * the @link ippNew@, @link ippNewRequest@, or @link ippNewResponse@ functions.
*
* The @code group@ parameter specifies the IPP attribute group tag: none
* (@code IPP_TAG_ZERO@, for member attributes), document (@code IPP_TAG_DOCUMENT@),
/*
* 'ippAddCollection()' - Add a collection value.
*
- * The @code ipp@ parameter refers to an IPP message previously created using the
- * @link ippNew@ or @link ippNewRequest@ functions.
+ * The @code ipp@ parameter refers to an IPP message previously created using
+ * the @link ippNew@, @link ippNewRequest@, or @link ippNewResponse@ functions.
*
* The @code group@ parameter specifies the IPP attribute group tag: none
* (@code IPP_TAG_ZERO@, for member attributes), document (@code IPP_TAG_DOCUMENT@),
/*
* 'ippAddCollections()' - Add an array of collection values.
*
- * The @code ipp@ parameter refers to an IPP message previously created using the
- * @link ippNew@ or @link ippNewRequest@ functions.
+ * The @code ipp@ parameter refers to an IPP message previously created using
+ * the @link ippNew@, @link ippNewRequest@, or @link ippNewResponse@ functions.
*
* The @code group@ parameter specifies the IPP attribute group tag: none
* (@code IPP_TAG_ZERO@, for member attributes), document (@code IPP_TAG_DOCUMENT@),
/*
* 'ippAddDate()' - Add a date attribute to an IPP message.
*
- * The @code ipp@ parameter refers to an IPP message previously created using the
- * @link ippNew@ or @link ippNewRequest@ functions.
+ * The @code ipp@ parameter refers to an IPP message previously created using
+ * the @link ippNew@, @link ippNewRequest@, or @link ippNewResponse@ functions.
*
* The @code group@ parameter specifies the IPP attribute group tag: none
* (@code IPP_TAG_ZERO@, for member attributes), document (@code IPP_TAG_DOCUMENT@),
/*
* 'ippAddInteger()' - Add a integer attribute to an IPP message.
*
- * The @code ipp@ parameter refers to an IPP message previously created using the
- * @link ippNew@ or @link ippNewRequest@ functions.
+ * The @code ipp@ parameter refers to an IPP message previously created using
+ * the @link ippNew@, @link ippNewRequest@, or @link ippNewResponse@ functions.
*
* The @code group@ parameter specifies the IPP attribute group tag: none
* (@code IPP_TAG_ZERO@, for member attributes), document (@code IPP_TAG_DOCUMENT@),
/*
* 'ippAddIntegers()' - Add an array of integer values.
*
- * The @code ipp@ parameter refers to an IPP message previously created using the
- * @link ippNew@ or @link ippNewRequest@ functions.
+ * The @code ipp@ parameter refers to an IPP message previously created using
+ * the @link ippNew@, @link ippNewRequest@, or @link ippNewResponse@ functions.
*
* The @code group@ parameter specifies the IPP attribute group tag: none
* (@code IPP_TAG_ZERO@, for member attributes), document (@code IPP_TAG_DOCUMENT@),
/*
* 'ippAddOctetString()' - Add an octetString value to an IPP message.
*
- * The @code ipp@ parameter refers to an IPP message previously created using the
- * @link ippNew@ or @link ippNewRequest@ functions.
+ * The @code ipp@ parameter refers to an IPP message previously created using
+ * the @link ippNew@, @link ippNewRequest@, or @link ippNewResponse@ functions.
*
* The @code group@ parameter specifies the IPP attribute group tag: none
* (@code IPP_TAG_ZERO@, for member attributes), document (@code IPP_TAG_DOCUMENT@),
/*
* 'ippAddOutOfBand()' - Add an out-of-band value to an IPP message.
*
- * The @code ipp@ parameter refers to an IPP message previously created using the
- * @link ippNew@ or @link ippNewRequest@ functions.
+ * The @code ipp@ parameter refers to an IPP message previously created using
+ * the @link ippNew@, @link ippNewRequest@, or @link ippNewResponse@ functions.
*
* The @code group@ parameter specifies the IPP attribute group tag: none
* (@code IPP_TAG_ZERO@, for member attributes), document (@code IPP_TAG_DOCUMENT@),
/*
* 'ippAddRange()' - Add a range of values to an IPP message.
*
- * The @code ipp@ parameter refers to an IPP message previously created using the
- * @link ippNew@ or @link ippNewRequest@ functions.
+ * The @code ipp@ parameter refers to an IPP message previously created using
+ * the @link ippNew@, @link ippNewRequest@, or @link ippNewResponse@ functions.
*
* The @code group@ parameter specifies the IPP attribute group tag: none
* (@code IPP_TAG_ZERO@, for member attributes), document (@code IPP_TAG_DOCUMENT@),
/*
* 'ippAddRanges()' - Add ranges of values to an IPP message.
*
- * The @code ipp@ parameter refers to an IPP message previously created using the
- * @link ippNew@ or @link ippNewRequest@ functions.
+ * The @code ipp@ parameter refers to an IPP message previously created using
+ * the @link ippNew@, @link ippNewRequest@, or @link ippNewResponse@ functions.
*
* The @code group@ parameter specifies the IPP attribute group tag: none
* (@code IPP_TAG_ZERO@, for member attributes), document (@code IPP_TAG_DOCUMENT@),
/*
* 'ippAddResolution()' - Add a resolution value to an IPP message.
*
- * The @code ipp@ parameter refers to an IPP message previously created using the
- * @link ippNew@ or @link ippNewRequest@ functions.
+ * The @code ipp@ parameter refers to an IPP message previously created using
+ * the @link ippNew@, @link ippNewRequest@, or @link ippNewResponse@ functions.
*
* The @code group@ parameter specifies the IPP attribute group tag: none
* (@code IPP_TAG_ZERO@, for member attributes), document (@code IPP_TAG_DOCUMENT@),
/*
* 'ippAddResolutions()' - Add resolution values to an IPP message.
*
- * The @code ipp@ parameter refers to an IPP message previously created using the
- * @link ippNew@ or @link ippNewRequest@ functions.
+ * The @code ipp@ parameter refers to an IPP message previously created using
+ * the @link ippNew@, @link ippNewRequest@, or @link ippNewResponse@ functions.
*
* The @code group@ parameter specifies the IPP attribute group tag: none
* (@code IPP_TAG_ZERO@, for member attributes), document (@code IPP_TAG_DOCUMENT@),
/*
* 'ippAddSeparator()' - Add a group separator to an IPP message.
*
- * The @code ipp@ parameter refers to an IPP message previously created using the
- * @link ippNew@ or @link ippNewRequest@ functions.
+ * The @code ipp@ parameter refers to an IPP message previously created using
+ * the @link ippNew@, @link ippNewRequest@, or @link ippNewResponse@ functions.
*/
ipp_attribute_t * /* O - New attribute */
/*
* 'ippAddString()' - Add a language-encoded string to an IPP message.
*
- * The @code ipp@ parameter refers to an IPP message previously created using the
- * @link ippNew@ or @link ippNewRequest@ functions.
+ * The @code ipp@ parameter refers to an IPP message previously created using
+ * the @link ippNew@, @link ippNewRequest@, or @link ippNewResponse@ functions.
*
* The @code group@ parameter specifies the IPP attribute group tag: none
* (@code IPP_TAG_ZERO@, for member attributes), document (@code IPP_TAG_DOCUMENT@),
}
+/*
+ * 'ippAddStringf()' - Add a formatted string to an IPP message.
+ *
+ * The @code ipp@ parameter refers to an IPP message previously created using
+ * the @link ippNew@, @link ippNewRequest@, or @link ippNewResponse@ functions.
+ *
+ * The @code group@ parameter specifies the IPP attribute group tag: none
+ * (@code IPP_TAG_ZERO@, for member attributes), document
+ * (@code IPP_TAG_DOCUMENT@), event notification
+ * (@code IPP_TAG_EVENT_NOTIFICATION@), operation (@code IPP_TAG_OPERATION@),
+ * printer (@code IPP_TAG_PRINTER@), subscription (@code IPP_TAG_SUBSCRIPTION@),
+ * or unsupported (@code IPP_TAG_UNSUPPORTED_GROUP@).
+ *
+ * Supported string values include charset (@code IPP_TAG_CHARSET@), keyword
+ * (@code IPP_TAG_KEYWORD@), language (@code IPP_TAG_LANGUAGE@), mimeMediaType
+ * (@code IPP_TAG_MIMETYPE@), name (@code IPP_TAG_NAME@), nameWithLanguage
+ * (@code IPP_TAG_NAMELANG), text (@code IPP_TAG_TEXT@), textWithLanguage
+ * (@code IPP_TAG_TEXTLANG@), uri (@code IPP_TAG_URI@), and uriScheme
+ * (@code IPP_TAG_URISCHEME@).
+ *
+ * The @code language@ parameter must be non-@code NULL@ for nameWithLanguage
+ * and textWithLanguage string values and must be @code NULL@ for all other
+ * string values.
+ *
+ * The @code format@ parameter uses formatting characters compatible with the
+ * printf family of standard functions. Additional arguments follow it as
+ * needed. The formatted string is truncated as needed to the maximum length of
+ * the corresponding value type.
+ *
+ * @since CUPS 1.7@
+ */
+
+ipp_attribute_t * /* O - New attribute */
+ippAddStringf(ipp_t *ipp, /* I - IPP message */
+ ipp_tag_t group, /* I - IPP group */
+ ipp_tag_t value_tag, /* I - Type of attribute */
+ const char *name, /* I - Name of attribute */
+ const char *language, /* I - Language code (@code NULL@ for default) */
+ const char *format, /* I - Printf-style format string */
+ ...) /* I - Additional arguments as needed */
+{
+ ipp_attribute_t *attr; /* New attribute */
+ va_list ap; /* Argument pointer */
+
+
+ va_start(ap, format);
+ attr = ippAddStringfv(ipp, group, value_tag, name, language, format, ap);
+ va_end(ap);
+
+ return (attr);
+}
+
+
+/*
+ * 'ippAddStringfv()' - Add a formatted string to an IPP message.
+ *
+ * The @code ipp@ parameter refers to an IPP message previously created using
+ * the @link ippNew@, @link ippNewRequest@, or @link ippNewResponse@ functions.
+ *
+ * The @code group@ parameter specifies the IPP attribute group tag: none
+ * (@code IPP_TAG_ZERO@, for member attributes), document
+ * (@code IPP_TAG_DOCUMENT@), event notification
+ * (@code IPP_TAG_EVENT_NOTIFICATION@), operation (@code IPP_TAG_OPERATION@),
+ * printer (@code IPP_TAG_PRINTER@), subscription (@code IPP_TAG_SUBSCRIPTION@),
+ * or unsupported (@code IPP_TAG_UNSUPPORTED_GROUP@).
+ *
+ * Supported string values include charset (@code IPP_TAG_CHARSET@), keyword
+ * (@code IPP_TAG_KEYWORD@), language (@code IPP_TAG_LANGUAGE@), mimeMediaType
+ * (@code IPP_TAG_MIMETYPE@), name (@code IPP_TAG_NAME@), nameWithLanguage
+ * (@code IPP_TAG_NAMELANG), text (@code IPP_TAG_TEXT@), textWithLanguage
+ * (@code IPP_TAG_TEXTLANG@), uri (@code IPP_TAG_URI@), and uriScheme
+ * (@code IPP_TAG_URISCHEME@).
+ *
+ * The @code language@ parameter must be non-@code NULL@ for nameWithLanguage
+ * and textWithLanguage string values and must be @code NULL@ for all other
+ * string values.
+ *
+ * The @code format@ parameter uses formatting characters compatible with the
+ * printf family of standard functions. Additional arguments are passed in the
+ * stdarg pointer @code ap@. The formatted string is truncated as needed to the
+ * maximum length of the corresponding value type.
+ *
+ * @since CUPS 1.7@
+ */
+
+ipp_attribute_t * /* O - New attribute */
+ippAddStringfv(ipp_t *ipp, /* I - IPP message */
+ ipp_tag_t group, /* I - IPP group */
+ ipp_tag_t value_tag, /* I - Type of attribute */
+ const char *name, /* I - Name of attribute */
+ const char *language, /* I - Language code (@code NULL@ for default) */
+ const char *format, /* I - Printf-style format string */
+ va_list ap) /* I - Additional arguments */
+{
+ char buffer[IPP_MAX_TEXT + 4];
+ /* Formatted text string */
+ ssize_t bytes, /* Length of formatted value */
+ max_bytes; /* Maximum number of bytes for value */
+
+
+ /*
+ * Range check input...
+ */
+
+ if (!ipp || !name || group < IPP_TAG_ZERO ||
+ group == IPP_TAG_END || group >= IPP_TAG_UNSUPPORTED_VALUE ||
+ (value_tag < IPP_TAG_TEXT && value_tag != IPP_TAG_TEXTLANG &&
+ value_tag != IPP_TAG_NAMELANG) || value_tag > IPP_TAG_MIMETYPE ||
+ !format || !ap)
+ return (NULL);
+
+ if ((value_tag == IPP_TAG_TEXTLANG || value_tag == IPP_TAG_NAMELANG)
+ != (language != NULL))
+ return (NULL);
+
+ /*
+ * Format the string...
+ */
+
+ if (!strcmp(format, "%s"))
+ {
+ /*
+ * Optimize the simple case...
+ */
+
+ const char *s = va_arg(ap, char *);
+
+ if (!s)
+ s = "(null)";
+
+ bytes = strlen(s);
+ strlcpy(buffer, s, sizeof(buffer));
+ }
+ else
+ {
+ /*
+ * Do a full formatting of the message...
+ */
+
+ if ((bytes = vsnprintf(buffer, sizeof(buffer), format, ap)) < 0)
+ return (NULL);
+ }
+
+ /*
+ * Limit the length of the string...
+ */
+
+ switch (value_tag)
+ {
+ default :
+ case IPP_TAG_TEXT :
+ case IPP_TAG_TEXTLANG :
+ max_bytes = IPP_MAX_TEXT;
+ break;
+
+ case IPP_TAG_NAME :
+ case IPP_TAG_NAMELANG :
+ max_bytes = IPP_MAX_NAME;
+ break;
+
+ case IPP_TAG_CHARSET :
+ max_bytes = IPP_MAX_CHARSET;
+ break;
+
+ case IPP_TAG_KEYWORD :
+ max_bytes = IPP_MAX_KEYWORD;
+ break;
+
+ case IPP_TAG_LANGUAGE :
+ max_bytes = IPP_MAX_LANGUAGE;
+ break;
+
+ case IPP_TAG_MIMETYPE :
+ max_bytes = IPP_MAX_MIMETYPE;
+ break;
+
+ case IPP_TAG_URI :
+ max_bytes = IPP_MAX_URI;
+ break;
+
+ case IPP_TAG_URISCHEME :
+ max_bytes = IPP_MAX_URISCHEME;
+ break;
+ }
+
+ if (bytes >= max_bytes)
+ {
+ char *bufmax, /* Buffer at max_bytes */
+ *bufptr; /* Pointer into buffer */
+
+ bufptr = buffer + strlen(buffer) - 1;
+ bufmax = buffer + max_bytes - 1;
+
+ while (bufptr > bufmax)
+ {
+ if (*bufptr & 0x80)
+ {
+ while ((*bufptr & 0xc0) == 0x80 && bufptr > buffer)
+ bufptr --;
+ }
+
+ bufptr --;
+ }
+
+ *bufptr = '\0';
+ }
+
+ /*
+ * Add the formatted string and return...
+ */
+
+ return (ippAddString(ipp, group, value_tag, name, language, buffer));
+}
+
+
/*
* 'ippAddStrings()' - Add language-encoded strings to an IPP message.
*
- * The @code ipp@ parameter refers to an IPP message previously created using the
- * @link ippNew@ or @link ippNewRequest@ functions.
+ * The @code ipp@ parameter refers to an IPP message previously created using
+ * the @link ippNew@, @link ippNewRequest@, or @link ippNewResponse@ functions.
*
* The @code group@ parameter specifies the IPP attribute group tag: none
* (@code IPP_TAG_ZERO@, for member attributes), document (@code IPP_TAG_DOCUMENT@),
}
+/*
+ * 'ippNewResponse()' - Allocate a new IPP response message.
+ *
+ * The new response message is initialized with the same version-number,
+ * request-id, attributes-charset, and attributes-natural-language as the
+ * provided request message. If the attributes-charset or
+ * attributes-natural-language attributes are missing from the request,
+ * "utf-8" and a value derived from the current locale are substituted,
+ * respectively.
+ *
+ * @since CUPS 1.7@
+ */
+
+ipp_t * /* O - IPP response message */
+ippNewResponse(ipp_t *request) /* I - IPP request message */
+{
+ ipp_t *response; /* IPP response message */
+ ipp_attribute_t *attr; /* Current attribute */
+
+
+ /*
+ * Range check input...
+ */
+
+ if (!request)
+ return (NULL);
+
+ /*
+ * Create a new IPP message...
+ */
+
+ if ((response = ippNew()) == NULL)
+ return (NULL);
+
+ /*
+ * Copy the request values over to the response...
+ */
+
+ response->request.status.version[0] = request->request.op.version[0];
+ response->request.status.version[1] = request->request.op.version[1];
+ response->request.status.request_id = request->request.op.request_id;
+
+ /*
+ * The first attribute MUST be attributes-charset...
+ */
+
+ attr = request->attrs;
+
+ if (attr && attr->name && !strcmp(attr->name, "attributes-charset") &&
+ attr->group_tag == IPP_TAG_OPERATION &&
+ attr->value_tag == IPP_TAG_CHARSET &&
+ attr->num_values == 1)
+ {
+ /*
+ * Copy charset from request...
+ */
+
+ ippAddString(response, IPP_TAG_OPERATION, IPP_TAG_CHARSET,
+ "attributes-charset", NULL, attr->values[0].string.text);
+ }
+ else
+ {
+ /*
+ * Use "utf-8" as the default...
+ */
+
+ ippAddString(response, IPP_TAG_OPERATION, IPP_TAG_CHARSET,
+ "attributes-charset", NULL, "utf-8");
+ }
+
+ /*
+ * Then attributes-natural-language...
+ */
+
+ if (attr)
+ attr = attr->next;
+
+ if (attr && attr->name &&
+ !strcmp(attr->name, "attributes-natural-language") &&
+ attr->group_tag == IPP_TAG_OPERATION &&
+ attr->value_tag == IPP_TAG_LANGUAGE &&
+ attr->num_values == 1)
+ {
+ /*
+ * Copy language from request...
+ */
+
+ ippAddString(response, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE,
+ "attributes-natural-language", NULL,
+ attr->values[0].string.text);
+ }
+ else
+ {
+ /*
+ * Use the language from the current locale...
+ */
+
+ cups_lang_t *language = cupsLangDefault();
+ /* Current locale */
+
+ ippAddString(response, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE,
+ "attributes-natural-language", NULL, language->language);
+ }
+
+ return (response);
+}
+
+
/*
* 'ippRead()' - Read data for an IPP message from a HTTP connection.
*/
/*
* 'ippSetBoolean()' - Set a boolean value in an attribute.
*
- * The @code ipp@ parameter refers to the IPP message containing the attribute that was
- * previously created using the @link ippNew@ or @link ippNewRequest@ functions.
+ * The @code ipp@ parameter refers to an IPP message previously created using
+ * the @link ippNew@, @link ippNewRequest@, or @link ippNewResponse@ functions.
*
* The @code attr@ parameter may be modified as a result of setting the value.
*
/*
* 'ippSetCollection()' - Set a collection value in an attribute.
*
- * The @code ipp@ parameter refers to the IPP message containing the attribute that was
- * previously created using the @link ippNew@ or @link ippNewRequest@ functions.
+ * The @code ipp@ parameter refers to an IPP message previously created using
+ * the @link ippNew@, @link ippNewRequest@, or @link ippNewResponse@ functions.
*
* The @code attr@ parameter may be modified as a result of setting the value.
*
/*
* 'ippSetDate()' - Set a date value in an attribute.
*
- * The @code ipp@ parameter refers to the IPP message containing the attribute that was
- * previously created using the @link ippNew@ or @link ippNewRequest@ functions.
+ * The @code ipp@ parameter refers to an IPP message previously created using
+ * the @link ippNew@, @link ippNewRequest@, or @link ippNewResponse@ functions.
*
* The @code attr@ parameter may be modified as a result of setting the value.
*
/*
* 'ippSetGroupTag()' - Set the group tag of an attribute.
*
- * The @code ipp@ parameter refers to the IPP message containing the attribute that was
- * previously created using the @link ippNew@ or @link ippNewRequest@ functions.
+ * The @code ipp@ parameter refers to an IPP message previously created using
+ * the @link ippNew@, @link ippNewRequest@, or @link ippNewResponse@ functions.
*
* The @code attr@ parameter may be modified as a result of setting the value.
*
/*
* 'ippSetInteger()' - Set an integer or enum value in an attribute.
*
- * The @code ipp@ parameter refers to the IPP message containing the attribute that was
- * previously created using the @link ippNew@ or @link ippNewRequest@ functions.
+ * The @code ipp@ parameter refers to an IPP message previously created using
+ * the @link ippNew@, @link ippNewRequest@, or @link ippNewResponse@ functions.
*
* The @code attr@ parameter may be modified as a result of setting the value.
*
/*
* 'ippSetName()' - Set the name of an attribute.
*
- * The @code ipp@ parameter refers to the IPP message containing the attribute that was
- * previously created using the @link ippNew@ or @link ippNewRequest@ functions.
+ * The @code ipp@ parameter refers to an IPP message previously created using
+ * the @link ippNew@, @link ippNewRequest@, or @link ippNewResponse@ functions.
*
* The @code attr@ parameter may be modified as a result of setting the value.
*
/*
* 'ippSetOperation()' - Set the operation ID in an IPP request message.
*
- * The @code ipp@ parameter refers to an IPP message previously created using the
- * @link ippNew@ or @link ippNewRequest@ functions.
+ * The @code ipp@ parameter refers to an IPP message previously created using
+ * the @link ippNew@, @link ippNewRequest@, or @link ippNewResponse@ functions.
*
* @since CUPS 1.6/OS X 10.8@
*/
/*
* 'ippSetRange()' - Set a rangeOfInteger value in an attribute.
*
- * The @code ipp@ parameter refers to the IPP message containing the attribute that was
- * previously created using the @link ippNew@ or @link ippNewRequest@ functions.
+ * The @code ipp@ parameter refers to an IPP message previously created using
+ * the @link ippNew@, @link ippNewRequest@, or @link ippNewResponse@ functions.
*
* The @code attr@ parameter may be modified as a result of setting the value.
*
/*
* 'ippSetRequestId()' - Set the request ID in an IPP message.
*
- * The @code ipp@ parameter refers to an IPP message previously created using the
- * @link ippNew@ or @link ippNewRequest@ functions.
+ * The @code ipp@ parameter refers to an IPP message previously created using
+ * the @link ippNew@, @link ippNewRequest@, or @link ippNewResponse@ functions.
*
* The @code request_id@ parameter must be greater than 0.
*
/*
* 'ippSetResolution()' - Set a resolution value in an attribute.
*
- * The @code ipp@ parameter refers to the IPP message containing the attribute that was
- * previously created using the @link ippNew@ or @link ippNewRequest@ functions.
+ * The @code ipp@ parameter refers to an IPP message previously created using
+ * the @link ippNew@, @link ippNewRequest@, or @link ippNewResponse@ functions.
*
* The @code attr@ parameter may be modified as a result of setting the value.
*
/*
* 'ippSetStatusCode()' - Set the status code in an IPP response or event message.
*
- * The @code ipp@ parameter refers to an IPP message previously created using the
- * @link ippNew@ or @link ippNewRequest@ functions.
+ * The @code ipp@ parameter refers to an IPP message previously created using
+ * the @link ippNew@, @link ippNewRequest@, or @link ippNewResponse@ functions.
*
* @since CUPS 1.6/OS X 10.8@
*/
/*
* 'ippSetString()' - Set a string value in an attribute.
*
- * The @code ipp@ parameter refers to the IPP message containing the attribute that was
- * previously created using the @link ippNew@ or @link ippNewRequest@ functions.
+ * The @code ipp@ parameter refers to an IPP message previously created using
+ * the @link ippNew@, @link ippNewRequest@, or @link ippNewResponse@ functions.
*
* The @code attr@ parameter may be modified as a result of setting the value.
*
/*
* 'ippSetValueTag()' - Set the value tag of an attribute.
*
- * The @code ipp@ parameter refers to the IPP message containing the attribute that was
- * previously created using the @link ippNew@ or @link ippNewRequest@ functions.
+ * The @code ipp@ parameter refers to an IPP message previously created using
+ * the @link ippNew@, @link ippNewRequest@, or @link ippNewResponse@ functions.
*
* The @code attr@ parameter may be modified as a result of setting the value.
*
/*
* 'ippSetVersion()' - Set the version number in an IPP message.
*
- * The @code ipp@ parameter refers to an IPP message previously created using the
- * @link ippNew@ or @link ippNewRequest@ functions.
+ * The @code ipp@ parameter refers to an IPP message previously created using
+ * the @link ippNew@, @link ippNewRequest@, or @link ippNewResponse@ functions.
*
* The valid version numbers are currently 1.0, 1.1, 2.0, 2.1, and 2.2.
*
extern int ippSetVersion(ipp_t *ipp, int major, int minor)
_CUPS_API_1_6;
+/**** New in CUPS 1.7 ****/
+extern ipp_attribute_t *ippAddStringf(ipp_t *ipp, ipp_tag_t group,
+ ipp_tag_t value_tag, const char *name,
+ const char *language, const char *format,
+ ...) _CUPS_API_1_7;
+extern ipp_attribute_t *ippAddStringfv(ipp_t *ipp, ipp_tag_t group,
+ ipp_tag_t value_tag, const char *name,
+ const char *language,
+ const char *format, va_list ap)
+ _CUPS_API_1_7;
+extern ipp_t *ippNewResponse(ipp_t *request) _CUPS_API_1_7;
+
/*
* C++ magic...
}
httpPrintf(HTTP(con), "Connection: Upgrade\r\n");
- httpPrintf(HTTP(con), "Upgrade: TLS/1.0,HTTP/1.1\r\n");
+ httpPrintf(HTTP(con), "Upgrade: TLS/1.2,TLS/1.1,TLS/1.0\r\n");
httpPrintf(HTTP(con), "Content-Length: 0\r\n");
httpPrintf(HTTP(con), "\r\n");
}
httpPrintf(HTTP(con), "Connection: Upgrade\r\n");
- httpPrintf(HTTP(con), "Upgrade: TLS/1.0,HTTP/1.1\r\n");
+ httpPrintf(HTTP(con), "Upgrade: TLS/1.2,TLS/1.1,TLS/1.0\r\n");
httpPrintf(HTTP(con), "Content-Length: 0\r\n");
httpPrintf(HTTP(con), "\r\n");