diff --git a/README.md b/README.md

index 3c999cee8bbcb5b0bfbc6732f9ecea0ba231d043..6dcd2f7b6f5e9d408b03fa2aae5c386fd3121aa1 100644

--- a/README.md

+++ b/README.md

@@ -60,6 +60,6 @@

Dependencies:

-- OpenSSL

+- BearSSL

diff --git a/config.sh b/config.sh

index 424cbda346869c7476859d55a600c414c86bbb46..87888929b98a46887dbcb25378385183e4ef2566 100644

--- a/config.sh

+++ b/config.sh

@@ -117,8 +117,8 @@ echo no

	fi

done

printf "Checking for scdoc... "

if scdoc -v >/dev/null 2>&1

diff --git a/include/gmni/gmni.h b/include/gmni/gmni.h

index 7e27b489d71fd3a43ca60292b17d56cab3caa5f8..16bef51024275bbb6ade9c90a11ae68876df387a 100644

--- a/include/gmni/gmni.h

+++ b/include/gmni/gmni.h

@@ -1,7 +1,7 @@

#ifndef GEMINI_CLIENT_H

#define GEMINI_CLIENT_H

+#include <bearssl_ssl.h>

#include <netdb.h>

-#include <openssl/ssl.h>

#include <stdbool.h>

#include <sys/socket.h>

@@ -52,20 +52,16 @@ struct gemini_response {

enum gemini_status status;

char *meta;

// Response body may be read from here if appropriate:

// Connection state

int fd;

};

struct gemini_options {

// If ai_family != AF_UNSPEC (the default value on most systems), the

// client will connect to this address and skip name resolution.

struct addrinfo *addr;

@@ -75,6 +71,8 @@ // example, to force IPv4/IPv6.

struct addrinfo *hints;

};

+struct gemini_tofu;

// Requests the specified URL via the gemini protocol. If options is non-NULL,

// it may specify some additional configuration to adjust client behavior.

//

@@ -84,6 +82,7 @@ // Caller must call gemini_response_finish afterwards to clean up resources

// before exiting or re-using it for another request.

enum gemini_result gemini_request(const char *url,

	struct gemini_options *options,

	struct gemini_response *resp);

// Must be called after gemini_request in order to free up the resources

@@ -137,15 +136,20 @@ };

};

struct gemini_parser {

char *buf;

size_t bufsz;

size_t bufln;

bool preformatted;

};

-// Initializes a text/gemini parser which reads from the specified BIO.

-void gemini_parser_init(struct gemini_parser *p, BIO *f);

+// Initializes a text/gemini parser. The provided "read" function will be called

+// with the provided "state" value in order to obtain more gemtext data. The

+// read function should behave like read(3).

+void gemini_parser_init(struct gemini_parser *p,

// Finishes this text/gemini parser and frees up its resources.

void gemini_parser_finish(struct gemini_parser *p);

diff --git a/include/gmni/tofu.h b/include/gmni/tofu.h

index a88167ba0fb6606b2b170e5005c55131f1861972..a0981a5296421541a766846bc36c733dab1dfd1a 100644

--- a/include/gmni/tofu.h

+++ b/include/gmni/tofu.h

@@ -1,9 +1,7 @@

#ifndef GEMINI_TOFU_H

#define GEMINI_TOFU_H

+#include <bearssl_x509.h>

#include <limits.h>

-#include <openssl/ssl.h>

-#include <openssl/x509.h>

-#include <time.h>

enum tofu_error {

TOFU_VALID,

@@ -24,7 +22,6 @@ };

struct known_host {

char *host, *fingerprint;

int lineno;

struct known_host *next;

};

@@ -34,7 +31,23 @@ // certificate. Return true to trust this certificate.

typedef enum tofu_action (tofu_callback_t)(enum tofu_error error,

const char *fingerprint, struct known_host *host, void *data);

+struct gemini_tofu;

+struct x509_tofu_context {

+};

struct gemini_tofu {

char known_hosts_path[PATH_MAX+1];

struct known_host *known_hosts;

int lineno;

@@ -42,8 +55,7 @@ tofu_callback_t *callback;

void *cb_data;

};

-void gemini_tofu_init(struct gemini_tofu *tofu,

+void gemini_tofu_init(struct gemini_tofu *tofu, tofu_callback_t *cb, void *data);

void gemini_tofu_finish(struct gemini_tofu *tofu);

#endif

diff --git a/include/util.h b/include/util.h

index 6193fdf48c0ac6d313de7f35a1d09ecba62e3283..8ec9ac5d94092a75813a3e083140fbb88079c29d 100644

--- a/include/util.h

+++ b/include/util.h

@@ -1,5 +1,7 @@

#ifndef GEMINI_UTIL_H

#define GEMINI_UTIL_H

+#include <stdio.h>

+#include <sys/types.h>

struct pathspec {

const char *var;

diff --git a/src/client.c b/src/client.c

index a8a12f3cfbe1e98fd2045eec257cfaf95c319910..e402cc97d96a904a2a8e9e2db40345b222cb85ae 100644

--- a/src/client.c

+++ b/src/client.c

@@ -1,15 +1,15 @@

#include <assert.h>

#include <errno.h>

#include <netdb.h>

-#include <openssl/bio.h>

-#include <openssl/err.h>

-#include <openssl/ssl.h>

+#include <bearssl_ssl.h>

#include <stdlib.h>

+#include <stdio.h>

#include <string.h>

#include <sys/socket.h>

#include <sys/types.h>

#include <unistd.h>

#include <gmni/gmni.h>

+#include <gmni/tofu.h>

#include <gmni/url.h>

static enum gemini_result

@@ -88,9 +88,41 @@

#define GEMINI_META_MAXLEN 1024

#define GEMINI_STATUS_MAXLEN 2

+static int

+sock_read(void *ctx, unsigned char *buf, size_t len)

+{

+}

+static int

+sock_write(void *ctx, const unsigned char *buf, size_t len)

+{

+}

enum gemini_result

gemini_request(const char *url, struct gemini_options *options,

{

assert(url);

assert(resp);

@@ -128,84 +160,50 @@ free(host);

	goto cleanup;

}

int r;

res = gemini_connect(uri, options, resp, &resp->fd);

if (res != GEMINI_OK) {

	free(host);

	goto cleanup;

}

char req[1024 + 3];

r = snprintf(req, sizeof(req), "%s\r\n", url);

assert(r > 0);

char buf[GEMINI_META_MAXLEN

	+ GEMINI_STATUS_MAXLEN

	+ 2 /* CRLF */ + 1 /* NUL */];

}

	res = GEMINI_ERR_PROTOCOL;

	goto cleanup;

}

@@ -217,9 +215,9 @@ fprintf(stderr, "invalid status\n");

	res = GEMINI_ERR_PROTOCOL;

	goto cleanup;

}

cleanup:

curl_url_cleanup(uri);

@@ -237,26 +235,18 @@ if (!resp) {

	return;

}

}

free(resp->meta);

}

resp->meta = NULL;

}

@@ -277,11 +267,11 @@ return gai_strerror(resp->status);

case GEMINI_ERR_CONNECT:

	return strerror(errno);

case GEMINI_ERR_SSL:

case GEMINI_ERR_SSL_VERIFY:

case GEMINI_ERR_IO:

	return "I/O error";

case GEMINI_ERR_PROTOCOL:

diff --git a/src/gmni.c b/src/gmni.c

index 49abb8524a012c27249006dc45f4688a846e63c3..a8321d06c367128706d19ac283a53e55d95d0a92 100644

--- a/src/gmni.c

+++ b/src/gmni.c

@@ -1,9 +1,8 @@

#include <assert.h>

+#include <bearssl_ssl.h>

#include <errno.h>

#include <getopt.h>

#include <netdb.h>

-#include <openssl/bio.h>

-#include <openssl/err.h>

#include <stdbool.h>

#include <stdio.h>

#include <stdlib.h>

@@ -222,10 +221,7 @@ usage(argv[0]);

	return 1;

}

bool exit = false;

struct Curl_URL *url = curl_url();

@@ -242,7 +238,8 @@ char *buf;

	curl_url_get(url, CURLUPART_URL, &buf, 0);

	struct gemini_response resp;

	free(buf);

@@ -340,11 +337,8 @@

		char last = 0;

		char buf[BUFSIZ];

		for (int n = 1; n > 0;) {

				last = buf[n - 1];

			}

			ssize_t w = 0;

@@ -370,7 +364,6 @@ next:

	gemini_response_finish(&resp);

}

curl_url_cleanup(url);

gemini_tofu_finish(&cfg.tofu);

return ret;

diff --git a/src/gmnlm.c b/src/gmnlm.c

index f31222b3ee2c495ed42c614bbd3c5100b52ae767..0ea492bb85fe024bd250c304808dcb8f0a915f90 100644

--- a/src/gmnlm.c

+++ b/src/gmnlm.c

@@ -1,22 +1,25 @@

#include <assert.h>

+#include <bearssl_ssl.h>

#include <ctype.h>

+#include <errno.h>

+#include <fcntl.h>

#include <getopt.h>

+#include <gmni/gmni.h>

+#include <gmni/tofu.h>

+#include <gmni/url.h>

#include <libgen.h>

#include <limits.h>

-#include <openssl/bio.h>

-#include <openssl/err.h>

#include <regex.h>

#include <stdbool.h>

#include <stdio.h>

+#include <stdlib.h>

#include <string.h>

#include <sys/ioctl.h>

#include <sys/stat.h>

+#include <sys/types.h>

#include <sys/wait.h>

#include <termios.h>

#include <unistd.h>

-#include <gmni/gmni.h>

-#include <gmni/tofu.h>

-#include <gmni/url.h>

#include "util.h"

#define ANSI_COLOR_RED "\x1b[91m"

@@ -398,10 +401,13 @@ close(pfd[0]);

FILE *f = fdopen(pfd[1], "w");

// XXX: may affect history, do we care?

for (int n = 1; n > 0;) {

	}

	ssize_t w = 0;

	while (w < (ssize_t)n) {

@@ -445,23 +451,19 @@ resp->status = GEMINI_STATUS_BAD_REQUEST;

			break;

		}

			resp->status = GEMINI_STATUS_NOT_FOUND;

			resp->meta = NULL;

			resp->fd = -1;

			free(path);

			break;

		}

		if (has_suffix(path, ".gmi") || has_suffix(path, ".gemini")) {

			resp->meta = strdup("text/gemini");

		} else if (has_suffix(path, ".txt")) {

@@ -471,14 +473,14 @@ resp->meta = strdup("application/x-octet-stream");

		}

		free(path);

		resp->status = GEMINI_STATUS_SUCCESS;

		return GEMINI_OK;

	}

	free(scheme);

	if (res != GEMINI_OK) {

		fprintf(stderr, "Error: %s\n", gemini_strerr(res, resp));

		requesting = false;

@@ -835,12 +837,23 @@ }

return fprintf(f, "%s\n", s) - 1;

}

+static int

+resp_read(void *state, void *buf, size_t nbyte)

+{

+}

static bool

display_gemini(struct browser *browser, struct gemini_response *resp)

{

int nlinks = 0;

struct gemini_parser p;

free(browser->page_title);

browser->page_title = NULL;

@@ -1029,10 +1042,13 @@ ioctl(fileno(browser->tty), TIOCGWINSZ, &ws);

char buf[BUFSIZ];

for (int n = 1; n > 0;) {

	}

	ssize_t w = 0;

	while (w < (ssize_t)n) {

@@ -1207,11 +1223,7 @@ } else {

	open_bookmarks(&browser);

}

struct gemini_response resp;

browser.running = true;

@@ -1273,7 +1285,6 @@ while (hist && hist->prev) {

	hist = hist->prev;

}

history_free(hist);

curl_url_cleanup(browser.url);

free(browser.page_title);

free(browser.plain_url);

diff --git a/src/parser.c b/src/parser.c

index ad2c0e6306872f8dde450063ba8815e2ee7e314a..6f12456ddbe5248b59ea146464a1d76365505c56 100644

--- a/src/parser.c

+++ b/src/parser.c

@@ -1,21 +1,23 @@

#include <assert.h>

#include <ctype.h>

-#include <openssl/bio.h>

#include <stdbool.h>

#include <stddef.h>

+#include <stdio.h>

#include <stdlib.h>

#include <string.h>

#include <gmni/gmni.h>

void

-gemini_parser_init(struct gemini_parser *p, BIO *f)

+gemini_parser_init(struct gemini_parser *p,

{

p->bufln = 0;

p->bufsz = BUFSIZ;

p->buf = malloc(p->bufsz + 1);

p->buf[0] = 0;

p->preformatted = false;

}

@@ -25,7 +27,6 @@ {

if (!p) {

	return;

}

free(p->buf);

}

@@ -42,7 +43,7 @@ p->buf = realloc(p->buf, p->bufsz);

		assert(p->buf);

	}

	if (n == -1) {

		return -1;

	} else if (n == 0) {

diff --git a/src/tofu.c b/src/tofu.c

index 48395c08cdbf68b31c5defd15b360f1eb2897a3f..de2bc14ce6a7c269cd430c2beebd64d6b493913b 100644

--- a/src/tofu.c

+++ b/src/tofu.c

@@ -1,95 +1,97 @@

#include <assert.h>

+#include <bearssl_hash.h>

+#include <bearssl_x509.h>

#include <errno.h>

+#include <gmni/gmni.h>

+#include <gmni/tofu.h>

#include <libgen.h>

#include <limits.h>

-#include <openssl/asn1.h>

-#include <openssl/evp.h>

-#include <openssl/ssl.h>

-#include <openssl/x509.h>

-#include <openssl/x509v3.h>

+#include <stdint.h>

#include <stdio.h>

+#include <stdlib.h>

#include <string.h>

-#include <time.h>

-#include <gmni/gmni.h>

-#include <gmni/tofu.h>

#include "util.h"

-static int

-verify_callback(X509_STORE_CTX *ctx, void *data)

+static void

+xt_start_chain(const br_x509_class **ctx, const char *server_name)

{

+}

+static void

+xt_start_cert(const br_x509_class **ctx, uint32_t length)

+{

}

}

+}

+static void

+xt_append(const br_x509_class **ctx, const unsigned char *buf, size_t len)

+{

}

}

+}

+static void

+xt_end_cert(const br_x509_class **ctx)

+{

}

}

+}

+static unsigned

+xt_end_chain(const br_x509_class **ctx)

+{

}

enum tofu_error error = TOFU_UNTRUSTED_CERT;

while (host) {

		goto next;

	}

	if (strcmp(host->fingerprint, fingerprint) == 0) {

@@ -102,66 +104,84 @@ next:

	host = host->next;

}

-callback:

case TOFU_ASK:

	assert(0); // Invariant

case TOFU_FAIL:

case TOFU_TRUST_ONCE:

	// No further action necessary

	return 0;

case TOFU_TRUST_ALWAYS:;

	if (!f) {

		fprintf(stderr, "Error opening %s for writing: %s\n",

		break;

	};

	fclose(f);

	host = calloc(1, sizeof(struct known_host));

	host->fingerprint = strdup(fingerprint);

	return 0;

}

+}

-invalid_cert:

+static const br_x509_pkey *

+xt_get_pkey(const br_x509_class *const *ctx, unsigned *usages)

+{

}

+const br_x509_class xt_vtable = {

+};

+static void

+x509_init_tofu(struct x509_tofu_context *ctx, struct gemini_tofu *store)

+{

+}

void

-gemini_tofu_init(struct gemini_tofu *tofu,

+gemini_tofu_init(struct gemini_tofu *tofu, tofu_callback_t *cb, void *cb_data)

{

const struct pathspec paths[] = {

	{.var = "GMNIDATA", .path = "/%s"},

};

char *path_fmt = getpath(paths, sizeof(paths) / sizeof(paths[0]));

char dname[PATH_MAX+1];

size_t n = 0;

assert(n < sizeof(tofu->known_hosts_path));

strncpy(dname, dirname(tofu->known_hosts_path), sizeof(dname)-1);

@@ -179,10 +199,17 @@ free(path_fmt);

tofu->callback = cb;

tofu->cb_data = cb_data;

tofu->known_hosts = NULL;

FILE *f = fopen(tofu->known_hosts_path, "r");

if (!f) {

	return;

@@ -191,6 +218,11 @@ n = 0;

int lineno = 1;

char *line = NULL;

while (getline(&line, &n, f) != -1) {

	struct known_host *host = calloc(1, sizeof(struct known_host));

	char *tok = strtok(line, " ");

	assert(tok);

@@ -207,10 +239,6 @@

	tok = strtok(NULL, " ");

	assert(tok);

	host->fingerprint = strdup(tok);

	host->lineno = lineno++;

diff --git a/src/util.c b/src/util.c

index 2f62c29ce40ac012993e1d208d65491b56d204aa..780d0e8803ab9179683bd9a92cbead05624f2681 100644

--- a/src/util.c

+++ b/src/util.c

@@ -1,5 +1,7 @@

#include <assert.h>

+#include <bearssl_ssl.h>

#include <errno.h>

+#include <gmni/gmni.h>

#include <libgen.h>

#include <limits.h>

#include <stdint.h>

@@ -7,7 +9,6 @@ #include <stdio.h>

#include <stdlib.h>

#include <string.h>

#include <sys/stat.h>

-#include <gmni/gmni.h>

#include "util.h"

static void

@@ -82,7 +83,7 @@ }

fprintf(out, "Downloading %s to %s\n", url, path);

char buf[BUFSIZ];

for (int n = 1; n > 0;) {

	if (n == -1) {

		fprintf(stderr, "Error: read\n");

		return 1;

Proxy Information
Original URL
gemini://gmn.clttr.info:1965/sources/cgmnlm.git/commits/fc0bf889a3e5ce270600811875ef9a50729c4135.patch
Status Code
Success (20)
Meta
text/gemini
Capsule Response Time
166.351778 milliseconds
Gemini-to-HTML Time
10.790905 milliseconds

This content has been proxied by September (3851b).