Skip to content

Commit

Permalink
Merge HTTP and JSON changes from libcups v3, including httpConnectURI…
Browse files Browse the repository at this point in the history
… API.
  • Loading branch information
michaelrsweet committed Sep 9, 2024
1 parent aa32743 commit 0fa45ad
Show file tree
Hide file tree
Showing 3 changed files with 124 additions and 32 deletions.
108 changes: 108 additions & 0 deletions cups/http.c
Original file line number Diff line number Diff line change
Expand Up @@ -553,6 +553,114 @@ httpConnectEncrypt(
}


//
// '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.
//
Expand Down
1 change: 1 addition & 0 deletions cups/http.h
Original file line number Diff line number Diff line change
Expand Up @@ -406,6 +406,7 @@ extern http_t *httpConnect(const char *host, int port) _CUPS_DEPRECATED_MSG("Us
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.");
Expand Down
47 changes: 15 additions & 32 deletions cups/json.c
Original file line number Diff line number Diff line change
Expand Up @@ -194,7 +194,7 @@ cupsJSONExportFile(
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);
Expand Down Expand Up @@ -731,6 +731,13 @@ cupsJSONImportString(const char *s) // I - JSON string
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 '{'.");
Expand Down Expand Up @@ -1148,14 +1155,8 @@ cupsJSONImportURL(
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];
Expand All @@ -1174,26 +1175,8 @@ cupsJSONImportURL(
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...
Expand All @@ -1208,7 +1191,7 @@ cupsJSONImportURL(
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;
Expand All @@ -1232,7 +1215,7 @@ cupsJSONImportURL(
// 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;
Expand Down Expand Up @@ -1263,7 +1246,7 @@ cupsJSONImportURL(
break;
}

if (httpReconnect2(http, 30000, NULL))
if (!httpConnectAgain(http, /*msec*/30000, /*cancel*/NULL))
{
status = HTTP_STATUS_ERROR;
break;
Expand All @@ -1277,7 +1260,7 @@ cupsJSONImportURL(
httpFlush(http);

// Reconnect...
if (httpReconnect2(http, 30000, NULL))
if (!httpConnectAgain(http, /*msec*/30000, /*cancel*/NULL))
{
status = HTTP_STATUS_ERROR;
break;
Expand Down

0 comments on commit 0fa45ad

Please sign in to comment.