wdvi

network DVI viewer
Log | Files | Refs

commit e848acc216e73a29c7f76f868527344903eaa4ce
parent 463e7d79defcfdb1c364729b297901746cfdb221
Author: Kyle Milz <krwmilz@gmail.com>
Date:   Mon, 13 Sep 2021 18:56:54 +0000

rewrite parse_url using strsep()

Replace complicated url parsing using strlcpy() and strtonum() with strsep().
This makes the code shorter, and easier, to read, and we do not depend on
bsd functions. Also, we can pass a protocol string directly to
getaddrinfo(3) so do not convert port numbers to integers.

Some other small cleanups included.

Diffstat:
Mhttp.c | 87+++++++++++++++++++++++++++++--------------------------------------------------
1 file changed, 32 insertions(+), 55 deletions(-)

diff --git a/http.c b/http.c @@ -21,8 +21,7 @@ #include <assert.h> #include <err.h> /* err() */ -#include <stdlib.h> /* strtonum() */ -#include <string.h> /* strtok() */ +#include <string.h> /* strtok(), strsep() */ #include <unistd.h> /* close() */ #include <openssl/err.h> /* ERR_load_crypto_strings() */ @@ -38,16 +37,16 @@ struct url { const char *orig_url; - char hostname[128]; - int port; - char document[128]; + char *hostname; + char *port; + char *document; }; struct http_headers { char ver[15]; /* Should be enough, RFC2616 3.1 */ int stat; /* 200, 404, etc */ char stat_text[32]; /* 416 may be the longest? */ - int cont_len; /* Content-Length: */ + unsigned int cont_len; /* Content-Length: */ }; @@ -66,55 +65,33 @@ static struct url * parse_url(const char dest_url[]) { struct url *url; - const char *hostname_end; - const char *proto_loc; - const char *colon_loc; - const char *slash_loc; - char portnum[6]; - const char *errstr; + char *sep_url; + char *proto_loc; + char *reset; url = xmalloc(sizeof(struct url)); - url->port = 443; + url->port = "https"; url->orig_url = dest_url; + url->document = ""; - hostname_end = dest_url + strlen(dest_url); + /* dest_url[] will be modified */ + sep_url = xstrdup(dest_url); - /* Skip protocol if found. */ + /* Do not care if this is specified, https is assumed. */ if ((proto_loc = strstr(dest_url, "://"))) - dest_url = proto_loc + strlen("://"); - - colon_loc = strchr(dest_url, ':'); - slash_loc = strchr(dest_url, '/'); - - /* Try and parse port number if found. */ - if (colon_loc) { - hostname_end = colon_loc; - - if (slash_loc) - strlcpy(portnum, colon_loc + 1, slash_loc - colon_loc); - else - strlcpy(portnum, colon_loc + 1, sizeof(portnum)); - - /* Port numbers cannot be larger than 65535. */ - url->port = strtonum(portnum, 1, 64 * 1024 - 1, &errstr); - if (errstr != NULL) { - warning_popup_long("%s: port number '%s': %s", - "OK", NULL, - dest_url, portnum, errstr); - return NULL; - } - } + sep_url = proto_loc + strlen("://"); - /* Set document path if found. */ - if (slash_loc) { - strlcpy(url->document, slash_loc, sizeof(url->document)); + url->hostname = sep_url; - if (colon_loc == NULL) - hostname_end = slash_loc; - } else - strcpy(url->document, "/"); + reset = strsep(&sep_url, ":"); + if (sep_url != NULL) + url->port = sep_url; + else + sep_url = reset; - strlcpy(url->hostname, dest_url, hostname_end - dest_url + 1); + /* If found set document path */ + if (strsep(&sep_url, "/")) + url->document = sep_url; return url; } @@ -141,7 +118,7 @@ xconnect(struct url *url) hints.ai_family = AF_UNSPEC; hints.ai_socktype = SOCK_STREAM; - error = getaddrinfo(url->hostname, "https", &hints, &res0); + error = getaddrinfo(url->hostname, url->port, &hints, &res0); if (error) { warning_popup_long("%s: %s", "OK", NULL, url->hostname, gai_strerror(error)); @@ -220,7 +197,7 @@ tls_connect(int server, struct url *url) X509 *cert = NULL; X509_NAME *certname = NULL; BIO *outbio; - int ret, j, fprint_size; + unsigned int ret, j, fprint_size; const EVP_MD *fprint_type; unsigned char fprint[EVP_MAX_MD_SIZE]; EVP_PKEY *pkey = NULL; @@ -307,7 +284,7 @@ send_request(SSL *tls, struct url *url) char *req; int ret; - req_fmt = "GET %s HTTP/1.1\r\n" + req_fmt = "GET /%s HTTP/1.1\r\n" "Host: %s\r\n" "\r\n"; @@ -345,13 +322,13 @@ parse_headers(char *hdr, int hdr_len) goto free_res; /* First line of response is 'HTTP/1.1 200 OK' for example. */ - if (sscanf(line, "%15s %i %31s", res->ver, &res->stat, + if (sscanf(line, "%15s %i %31[^\0]", res->ver, &res->stat, res->stat_text) != 3) goto free_res; /* We only care about Content-Length right now. */ while ((line = strtok(NULL, "\r\n")) != NULL) { - if (sscanf(line, "Content-Length: %ui", &res->cont_len) == 1) + if (sscanf(line, "Content-Length: %u", &res->cont_len) == 1) return res; } @@ -369,8 +346,8 @@ read_response(SSL *tls, struct url *url) int total_bytes = 0; FILE *dvi_file = NULL; - /* We will be parsing text out of this, lets avoid surprises */ - buf = calloc(1, SSL_BUF_SIZE); + if ((buf = calloc(1, SSL_BUF_SIZE)) == NULL) + err(1, "calloc"); /* First read yields the HTTP header response in its entirety. */ if ((nbytes = SSL_read(tls, buf, SSL_BUF_SIZE)) < 1) { @@ -381,14 +358,14 @@ read_response(SSL *tls, struct url *url) /* We must free returned response. */ if ((resp = parse_headers(buf, nbytes)) == NULL) { - warning_popup_long("%s: malformed HTTP header", "OK", NULL, + warning_popup_long("%s: Malformed HTTP header", "OK", NULL, url->hostname); goto free_buf; } if (resp->stat != 200) { warning_popup_long("%s: %i %s", "OK", NULL, url->orig_url, - resp->stat, resp->stat_text); + resp->stat, resp->stat_text); goto free_resp; }