AmendHub

Download:

jcs

/

detritus

/

amendments

/

13

gemini: No need for a header file for this, it's all local functions


jcs made amendment 13 about 1 year ago
--- browser.c Thu Oct 24 17:21:12 2024 +++ browser.c Sat Oct 26 14:59:58 2024 @@ -27,12 +27,18 @@ #define BROWSER_FONT_SIZE 10 #define BROWSER_STATUS_FONT geneva #define BROWSER_STATUS_FONT_SIZE 9 +#define BROWSER_PRE_FONT monaco +#define BROWSER_PRE_FONT_SIZE 9 static Rect zerorect = { 0, 0, 0, 0 }; static Pattern fill_pattern; +extern struct request_handler gemini_handler; +extern struct request_handler gopher_handler; + struct request_handler * request_handlers[] = { &gemini_handler, + &gopher_handler, }; void browser_setup_shadow(struct browser *browser); @@ -606,6 +612,10 @@ browser_print(struct browser *browser, const char *str style.style |= italic; if (browser->style & STYLE_LINK) style.style |= underline; + if (browser->style & STYLE_PRE) { + style.font = BROWSER_PRE_FONT; + style.size = BROWSER_PRE_FONT_SIZE; + } if (browser->style & STYLE_H1) style.size += 8; @@ -614,84 +624,6 @@ browser_print(struct browser *browser, const char *str else if (browser->style & STYLE_H3) style.size += 2; - if (browser->style & STYLE_LINK) { - if (browser->links_count == browser->links_size) { - browser->links_size += BROWSER_LINKS_CHUNK_SIZE; - browser->links = xreallocarray(browser->links, - browser->links_size, sizeof(struct browser_link)); - if (browser->links == NULL) { - warn("Out of memory allocating links"); - return 0; - } - memset(&browser->links[browser->links_count], 0, - sizeof(struct browser_link) * BROWSER_LINKS_CHUNK_SIZE); - } - - link = &browser->links[browser->links_count++]; - - HLock(browser->output_tv); - link->pos = (*(browser->output_tv))->text_length; - HUnlock(browser->output_tv); - - /* [<whitespace>]<URL>[<whitespace><title>] */ - - /* eat leading whitespace */ - while (len && (str[0] == ' ' || str[0] == '\t')) { - str++; - len--; - } - - /* url, up to whitespace or end of str */ - for (n = 0; n <= len; n++) { - if (!(n == len || str[n] == ' ' || str[n] == '\t' || - str[n] == '\r')) - continue; - - if (n == len) - n--; - - link->link = xmalloc(n + 1); - if (link->link == NULL) { - warn("Out of memory allocating link"); - return 0; - } - memcpy(link->link, str, n); - link->link[n] = '\0'; - link->len = n; - str += n; - len -= n; - break; - } - - /* eat separating white space */ - while (len && (str[0] == ' ' || str[0] == '\t')) { - str++; - len--; - } - - /* optional title */ - if (len > 1) { - /* len will include trailing \r */ - - link->title = xmalloc(len); - if (link->title == NULL) { - warn("Out of memory allocating link title"); - return 0; - } - memcpy(link->title, str, len - 1); - link->title[len - 1] = '\0'; - link->len = len - 1; - - TVAppend(browser->output_tv, &style, link->title, len - 1); - - str += len - 1; - len = 1; - } else - TVAppend(browser->output_tv, &style, (char *)str, len); - - browser->style &= ~(STYLE_LINK); - } - if (str[len - 1] == '\r' && (browser->style & (STYLE_H1 | STYLE_H2 | STYLE_H3))) { /* print newlines in a small size */ @@ -706,6 +638,63 @@ browser_print(struct browser *browser, const char *str TVUpdateScrollbar(browser->output_tv, browser->output_tv_scroller); return len; +} + +size_t +browser_print_link(struct browser *browser, const char *url, size_t url_len, + const char *title, size_t title_len) +{ + struct TVStyle style; + struct browser_link *link; + size_t n; + + if (browser->links_count == browser->links_size) { + browser->links_size += BROWSER_LINKS_CHUNK_SIZE; + browser->links = xreallocarray(browser->links, + browser->links_size, sizeof(struct browser_link)); + if (browser->links == NULL) { + warn("Out of memory allocating links"); + return 0; + } + memset(&browser->links[browser->links_count], 0, + sizeof(struct browser_link) * BROWSER_LINKS_CHUNK_SIZE); + } + + link = &browser->links[browser->links_count++]; + + HLock(browser->output_tv); + link->pos = (*(browser->output_tv))->text_length; + HUnlock(browser->output_tv); + + link->link = xmalloc(url_len + 1); + if (link->link == NULL) { + warn("Out of memory allocating link"); + return 0; + } + memcpy(link->link, url, url_len); + link->link[n] = '\0'; + + browser->style |= STYLE_LINK; + + /* optional title */ + if (title_len > 1) { + link->title = xmalloc(title_len); + if (link->title == NULL) { + warn("Out of memory allocating link title"); + return 0; + } + memcpy(link->title, title, title_len + 1); + link->title[title_len] = '\0'; + link->len = title_len; + + browser_print(browser, link->title, title_len); + } else { + link->len = url_len; + browser_print(browser, url, url_len); + } + + browser->style &= ~(STYLE_LINK); + return link->len; } void --- browser.h Thu Oct 24 20:08:10 2024 +++ browser.h Sat Oct 26 14:53:08 2024 @@ -65,6 +65,8 @@ struct browser { struct browser * browser_init(void); size_t browser_statusf(struct browser *browser, const char *format, ...); +size_t browser_print_link(struct browser *browser, const char *url, + size_t url_len, const char *title, size_t title_len); size_t browser_print(struct browser *browser, const char *str, size_t len); //#define BROWSER_DEBUGF(x) browser_statusf #define BROWSER_DEBUGF(x) --- detritus.h Thu Oct 24 13:20:34 2024 +++ detritus.h Fri Oct 25 21:47:44 2024 @@ -18,7 +18,6 @@ #define __GEMINO_H__ #include "browser.h" -#include "gemini.h" #include "util.h" #define PROGRAM_NAME "Detritus" @@ -54,7 +53,7 @@ struct URI { #define URI_PATH_LEN 512 char path[URI_PATH_LEN + 1]; unsigned short port; - char str[1024]; + char str[800]; }; struct request_handler { @@ -67,6 +66,7 @@ struct request_handler { extern MenuHandle file_menu, edit_menu; void menu_defaults(void); +struct URI * generic_parse_uri(char *protocol, char *uristr); short scsi_find_tls(void); uint8_t scsi_tls_init(struct tls_init_request *req); --- gemini.c Thu Oct 24 20:19:40 2024 +++ gemini.c Sat Oct 26 14:54:01 2024 @@ -20,64 +20,74 @@ #include "detritus.h" -struct request_handler gemini_handler = { - gemini_parse_uri, - gemini_init_request, - gemini_process_request, - gemini_free, +#define GEMINI_PORT 1965 + +enum { + REQ_STATE_NEGOTIATING = 1, + REQ_STATE_SENDING_REQUEST, + REQ_STATE_PARSING_RESPONSE }; -bool shuffle_read_tls_ciphertext(struct gemini_request *req); -bool shuffle_read_tcp_ciphertext(struct gemini_request *req, short space); -bool shuffle_tls_send_plaintext(struct gemini_request *req, short space); -bool shuffle_tls_read_plaintext(struct gemini_request *req); -bool parse_response(struct gemini_request *req); -bool parse_header(struct gemini_request *req, char *str); -void consume_response(struct gemini_request *req, size_t len); +enum { + GEM_STATE_HEADER, + GEM_STATE_GEMTEXT, + GEM_STATE_REDIRECT, + GEM_STATE_DOWNLOAD +}; -struct URI * -gemini_parse_uri(char *uristr) -{ +struct gemini_request { + struct browser *browser; struct URI *uri; - short count; - uri = xmalloczero(sizeof(struct URI)); - if (uri == NULL) - return NULL; + uint8_t tls_id; + unsigned char tcp_buf[(4 * 1500) + 2048]; /* 4*MTU + tcp_input */ + unsigned char tcp_input[2048]; + size_t tcp_input_len; + short state; - uri->port = GEMINI_PORT; - snprintf(uri->protocol, sizeof(uri->protocol), "gemini"); + TCPiopb tcp_iopb; + StreamPtr tcp_stream; + wdsEntry tcp_wds[2]; + TCPStatusPB tcp_status_pb; + bool tcp_done_reading; - /* gemini://host/path */ - if (count = 0, sscanf(uristr, - "gemini://%" STR(URI_HOSTNAME_LEN) "[^/]/%" STR(URI_PATH_LEN) "s%n", - &uri->hostname, &uri->path + 1, &count) == 2 && count > 10) - goto parse_ok; + char message[member_size(struct URI, str) + 3]; + size_t message_len; - /* gemini://host/ */ - if (count = 0, sscanf(uristr, - "gemini://%" STR(URI_HOSTNAME_LEN) "[^/]/%n", - &uri->hostname, &count) == 1 && count > 10) { - snprintf(uri->path, sizeof(uri->path), "/"); - goto parse_ok; - } + short gem_state; + char response[1024]; + size_t response_len; + size_t total_response_len; - /* gemini://host */ - if (count = 0, sscanf(uristr, - "gemini://%" STR(URI_HOSTNAME_LEN) "[^/]%n", - &uri->hostname, &count) == 1 && count > 10) { - snprintf(uri->path, sizeof(uri->path), "/"); - goto parse_ok; - } - - /* failed */ - xfree(&uri); - return NULL; + char mime_type[64]; + unsigned long style; +}; -parse_ok: - snprintf(uri->str, sizeof(uri->str), "%s://%s%s", - uri->protocol, uri->hostname, uri->path); - return uri; +struct URI * gemini_parse_uri(char *uristr); +void * gemini_init_request(struct browser *browser, struct URI *uri); +bool gemini_process_request(void *cookie); +void gemini_free(void *cookie); +static bool shuffle_read_tls_ciphertext(struct gemini_request *req); +static bool shuffle_read_tcp_ciphertext(struct gemini_request *req, + short space); +static bool shuffle_tls_send_plaintext(struct gemini_request *req, + short space); +static bool shuffle_tls_read_plaintext(struct gemini_request *req); +static bool parse_response(struct gemini_request *req); +static bool parse_header(struct gemini_request *req, char *str); +static void consume_response(struct gemini_request *req, size_t len); + +struct request_handler gemini_handler = { + gemini_parse_uri, + gemini_init_request, + gemini_process_request, + gemini_free, +}; + +struct URI * +gemini_parse_uri(char *uristr) +{ + return generic_parse_uri("gemini", uristr); } void * @@ -99,6 +109,8 @@ gemini_init_request(struct browser *browser, struct UR req->browser = browser; req->uri = uri; + if (req->uri->port == 0) + req->uri->port = GEMINI_PORT; browser_statusf(browser, "Resolving \"%s\"...", req->uri->hostname); @@ -261,7 +273,7 @@ gemini_process_request(void *cookie) return true; } -bool +static bool shuffle_read_tls_ciphertext(struct gemini_request *req) { size_t len; @@ -297,7 +309,7 @@ shuffle_read_tls_ciphertext(struct gemini_request *req return true; } -bool +static bool shuffle_read_tcp_ciphertext(struct gemini_request *req, short space) { size_t len, n; @@ -375,7 +387,7 @@ forward_ciphertext: return true; } -bool +static bool shuffle_tls_send_plaintext(struct gemini_request *req, short space) { size_t slen, len; @@ -417,7 +429,7 @@ shuffle_tls_send_plaintext(struct gemini_request *req, return true; } -bool +static bool shuffle_tls_read_plaintext(struct gemini_request *req) { size_t len; @@ -452,7 +464,7 @@ shuffle_tls_read_plaintext(struct gemini_request *req) return true; } -bool +static bool parse_response(struct gemini_request *req) { size_t n, trail, skip, len; @@ -542,10 +554,10 @@ restart_parse: skip++; len--; } - req->browser->style = STYLE_LINK; - browser_print(req->browser, req->response + skip, len); - consume_response(req, skip + len + trail); + browser_print_link(req->browser, req->response + skip, + len, NULL, 0); req->browser->style = STYLE_NONE; + consume_response(req, skip + len + trail); goto restart_parse; } @@ -651,7 +663,7 @@ restart_parse: return true; } -void +static void consume_response(struct gemini_request *req, size_t len) { if (len == req->response_len) { @@ -666,7 +678,7 @@ consume_response(struct gemini_request *req, size_t le } } -bool +static bool parse_header(struct gemini_request *req, char *str) { short status; --- gemini.h Thu Oct 24 16:48:34 2024 +++ gemini.h Sat Oct 26 14:54:01 2024 @@ -1,76 +0,0 @@ -/* - * Copyright (c) 2021-2024 joshua stein <jcs@jcs.org> - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#include <stdarg.h> -#include <stdio.h> -#include <string.h> - -#include "detritus.h" - -#ifndef __GEMINI_H__ -#define __GEMINI_H__ - -#define GEMINI_PORT 1965 - -extern struct request_handler gemini_handler; - -enum { - REQ_STATE_NEGOTIATING = 1, - REQ_STATE_SENDING_REQUEST, - REQ_STATE_PARSING_RESPONSE -}; - -enum { - GEM_STATE_HEADER, - GEM_STATE_GEMTEXT, - GEM_STATE_REDIRECT, - GEM_STATE_DOWNLOAD -}; - -struct gemini_request { - struct browser *browser; - struct URI *uri; - - uint8_t tls_id; - unsigned char tcp_buf[(4 * 1500) + 2048]; /* 4*MTU + tcp_input */ - unsigned char tcp_input[2048]; - size_t tcp_input_len; - short state; - - TCPiopb tcp_iopb; - StreamPtr tcp_stream; - wdsEntry tcp_wds[2]; - TCPStatusPB tcp_status_pb; - bool tcp_done_reading; - - char message[1024 + 3]; - size_t message_len; - - short gem_state; - char response[1024]; - size_t response_len; - size_t total_response_len; - - char mime_type[64]; - unsigned long style; -}; - -struct URI * gemini_parse_uri(char *uristr); -void * gemini_init_request(struct browser *browser, struct URI *uri); -bool gemini_process_request(void *cookie); -void gemini_free(void *cookie); - -#endif \ No newline at end of file --- main.c Wed Oct 23 09:12:46 2024 +++ main.c Fri Oct 25 21:50:14 2024 @@ -231,3 +231,51 @@ handle_exit(void) { focusables_quit(); } + +struct URI * +generic_parse_uri(char *protocol, char *uristr) +{ + struct URI *uri; + short count; + + uri = xmalloczero(sizeof(struct URI)); + if (uri == NULL) + return NULL; + + /* protocol://host/path */ + if (count = 0, sscanf(uristr, + "%" STR(URI_PROTOCOL_LEN) "[^:]://%" STR(URI_HOSTNAME_LEN) "[^/]/%" + STR(URI_PATH_LEN) "s%n", + &uri->protocol, &uri->hostname, &uri->path + 1, &count) == 3 && + count > 10) + goto parse_ok; + + /* protocol://host/ */ + if (count = 0, sscanf(uristr, + "%" STR(URI_PROTOCOL_LEN) "[^:]://%" STR(URI_HOSTNAME_LEN) "[^/]/%n", + &uri->protocol, &uri->hostname, &count) == 2 && count > 10) { + snprintf(uri->path, sizeof(uri->path), "/"); + goto parse_ok; + } + + /* gemini://host */ + if (count = 0, sscanf(uristr, + "%" STR(URI_PROTOCOL_LEN) "[^:]://%" STR(URI_HOSTNAME_LEN) "[^/]%n", + &uri->protocol, &uri->hostname, &count) == 2 && count > 10) { + snprintf(uri->path, sizeof(uri->path), "/"); + goto parse_ok; + } + + /* failed */ + xfree(&uri); + return NULL; + +parse_ok: + if (protocol != NULL && strcasecmp(protocol, uri->protocol) != 0) { + xfree(&uri); + return NULL; + } + snprintf(uri->str, sizeof(uri->str), "%s://%s%s", + uri->protocol, uri->hostname, uri->path); + return uri; +}