}
+//
+// 'httpConnectURI()' - Connect to a HTTP service using a URI.
+//
+// This function creates a connection to a HTTP server. The "uri" argument
+// specifies a "http", "https", "ipp", or "ipps" URI for the service.
+//
+// The resource path for the service is returned in the buffer pointed to by
+// the "resource" argument of size "rsize".
+//
+// The "msec" argument specifies how long to try to connect to the server or `0`
+// to just create an unconnected `http_t` object. The "cancel" argument
+// specifies an integer variable that can be set to a non-zero value to cancel
+// the connection process.
+//
+// The "require_ca" argument specifies whether to verify that the service
+// connection is using a CA-signed X.509 certificate.
+//
+// @since CUPS 2.5@
+//
+
+http_t * // O - New HTTP connection
+httpConnectURI(const char *uri, // I - Service to connect to
+ char *host, // I - Host name buffer (`NULL` for don't care)
+ size_t hsize, // I - Size of host name buffer
+ int *port, // O - Port number (`NULL` for don't care)
+ char *resource, // I - Resource path buffer (`NULL` for don't care)
+ size_t rsize, // I - Size of resource path buffer
+ bool blocking, // I - `true` for blocking connection, `false` for non-blocking
+ int msec, // I - Connection timeout in milliseconds, `0` means don't connect
+ int *cancel, // I - Pointer to "cancel" variable or `NULL` for none
+ bool require_ca) // I - `true` to require a CA-signed X.509 certificate
+{
+ http_t *http; // New HTTP connection
+ char scheme[32], // URI scheme
+ userpass[32], // URI username:password
+ lhost[256], // URI host (local copy)
+ lresource[256]; // URI resource (local copy)
+ int lport; // URI port (local copy)
+ http_encryption_t encryption; // Type of encryption to use
+
+
+ DEBUG_printf("httpConnectURI(uri=\"%s\", host=%p, hsize=%u, port=%p, resource=%p, rsize=%u, blocking=%d, msec=%d, cancel=%p, require_ca=%s)", uri, (void *)host, (unsigned)hsize, (void *)port, (void *)resource, (unsigned)rsize, blocking, msec, (void *)cancel, require_ca ? "true" : "false");
+
+ // Range check input...
+ if (!uri)
+ {
+ if (host)
+ *host = '\0';
+
+ if (port)
+ *port = 0;
+
+ if (resource)
+ *resource = '\0';
+
+ return (NULL);
+ }
+
+ if (!host)
+ {
+ host = lhost;
+ hsize = sizeof(lhost);
+ }
+
+ if (!port)
+ port = &lport;
+
+ if (!resource)
+ {
+ resource = lresource;
+ rsize = sizeof(lresource);
+ }
+
+ // Get the URI components...
+ if (httpSeparateURI(HTTP_URI_CODING_ALL, uri, scheme, sizeof(scheme), userpass, sizeof(userpass), host, hsize, port, resource, rsize) < HTTP_URI_STATUS_OK)
+ return (NULL);
+
+ DEBUG_printf("1httpConnectURI: scheme=\"%s\", host=\"%s\", port=%d, resource=\"%s\"", scheme, host, *port, resource);
+
+ if (!strcmp(scheme, "https") || !strcmp(scheme, "ipps") || *port == 443)
+ encryption = HTTP_ENCRYPTION_ALWAYS;
+ else
+ encryption = HTTP_ENCRYPTION_IF_REQUESTED;
+
+ http = httpConnect2(host, *port, /*addrlist*/NULL, AF_UNSPEC, encryption, blocking, msec, cancel);
+
+ if (httpIsEncrypted(http) && require_ca)
+ {
+ // Validate trust with service...
+ char *creds; // Peer credentials...
+ http_trust_t trust; // Trust in credentials...
+
+ creds = httpCopyPeerCredentials(http);
+ trust = cupsGetCredentialsTrust(/*path*/NULL, host, creds, require_ca);
+
+ free(creds);
+
+ if (trust != HTTP_TRUST_OK)
+ {
+ httpClose(http);
+ http = NULL;
+ }
+ }
+
+ return (http);
+}
+
+
//
// 'httpDelete()' - Send a DELETE request to the server.
//
extern http_t *httpConnect2(const char *host, int port, http_addrlist_t *addrlist, int family, http_encryption_t encryption, int blocking, int msec, int *cancel) _CUPS_PUBLIC;
extern bool httpConnectAgain(http_t *http, int msec, int *cancel) _CUPS_PUBLIC;
extern http_t *httpConnectEncrypt(const char *host, int port, http_encryption_t encryption) _CUPS_DEPRECATED_MSG("Use httpConnect2 instead.");
+extern http_t *httpConnectURI(const char *uri, char *host, size_t hsize, int *port, char *resource, size_t rsize, bool blocking, int msec, int *cancel, bool require_ca) _CUPS_PUBLIC;
extern int httpCopyCredentials(http_t *http, cups_array_t **credentials) _CUPS_DEPRECATED_MSG("Use httpCopyPeerCredentials instead.");
extern char *httpCopyPeerCredentials(http_t *http) _CUPS_PUBLIC;
extern int httpCredentialsAreValidForName(cups_array_t *credentials, const char *common_name) _CUPS_DEPRECATED_MSG("Use cupsAreCredentialsValidForName instead.");
return (false);
// Create the file...
- if ((fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC, 0666)) < 0)
+ if ((fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC, 0664)) < 0)
{
_cupsSetError(IPP_STATUS_ERROR_INTERNAL, strerror(errno), 0);
free(s);
DEBUG_printf("cupsJSONImportString(s=\"%s\")", s);
// Range check input...
+ if (s)
+ {
+ // Skip leading whitespace...
+ while (*s && isspace(*s & 255))
+ s ++;
+ }
+
if (!s || *s != '{')
{
DEBUG_puts("2cupsJSONImportString: Doesn't start with '{'.");
const char *url, // I - URL
time_t *last_modified) // IO - Last modified date/time or `NULL`
{
- char scheme[32], // URL scheme
- userpass[64], // URL username:password info
- host[256], // URL hostname
- resource[1024]; // URL resource path
- int port; // URL port number
- http_uri_status_t uri_status; // URL decode status
- http_encryption_t encryption; // Encryption to use
http_t *http; // HTTP connection
+ char resource[1024]; // URL resource path
http_status_t status; // HTTP request status
http_state_t initial_state; // Initial HTTP state
char if_modified_since[HTTP_MAX_VALUE];
if (!url)
return (NULL);
- // Get the URL components...
- if ((uri_status = httpSeparateURI(HTTP_URI_CODING_ALL, url, scheme, sizeof(scheme), userpass, sizeof(userpass), host, sizeof(host), &port, resource, sizeof(resource))) < HTTP_URI_STATUS_OK)
- {
- _cupsSetError(IPP_STATUS_ERROR_INTERNAL, httpURIStatusString(uri_status), 0);
- return (NULL);
- }
-
- if (strcmp(scheme, "http") && strcmp(scheme, "https"))
- {
- _cupsSetError(IPP_STATUS_ERROR_INTERNAL, _("Unsupported URI scheme."), 1);
- return (NULL);
- }
-
- // Connect to the server...
- if (!strcmp(scheme, "https") || port == 443)
- encryption = HTTP_ENCRYPTION_ALWAYS;
- else
- encryption = HTTP_ENCRYPTION_IF_REQUESTED;
-
- if ((http = httpConnect2(host, port, NULL, AF_UNSPEC, encryption, true, 30000, NULL)) == NULL)
+ // Connect to the URI...
+ if ((http = httpConnectURI(url, /*host*/NULL, /*hsize*/0, /*port*/NULL, resource, sizeof(resource), /*blocking*/true, /*msec*/30000, /*cancel*/NULL, /*require_ca*/true)) == NULL)
return (NULL);
// Send a GET request for the resource path...
if (!_cups_strcasecmp(httpGetField(http, HTTP_FIELD_CONNECTION), "close"))
{
httpClearFields(http);
- if (httpReconnect2(http, 30000, NULL))
+ if (!httpConnectAgain(http, /*msec*/30000, /*cancel*/NULL))
{
status = HTTP_STATUS_ERROR;
break;
// Send the GET request...
if (!httpWriteRequest(http, "GET", resource))
{
- if (!httpReconnect2(http, 30000, NULL))
+ if (httpConnectAgain(http, /*msec*/30000, /*cancel*/NULL))
{
status = HTTP_STATUS_UNAUTHORIZED;
continue;
break;
}
- if (httpReconnect2(http, 30000, NULL))
+ if (!httpConnectAgain(http, /*msec*/30000, /*cancel*/NULL))
{
status = HTTP_STATUS_ERROR;
break;
httpFlush(http);
// Reconnect...
- if (httpReconnect2(http, 30000, NULL))
+ if (!httpConnectAgain(http, /*msec*/30000, /*cancel*/NULL))
{
status = HTTP_STATUS_ERROR;
break;