Recent Posts

Wasat v0.5.0

1 min read; 12 GFI

Another quick update to Wasat, my Gemini Protocol client library for Python.

With v0.5.0 I've added a method for getting the list of currently-trusted hosts, and also added a public property to the client class for getting access to the trust store object.

Generally these shouldn't be required, shouldn't be something you'd normally want to work with; I've added them because I thought it might be another useful way of populating the suggested completions facility in the command line inside Rogallo. The idea being: if you're trying to remember the name of a capsule you've visited before, and it might have fallen out of the location history, its trust status might still be recorded so it can complete from there.

Let down by Openreach (again)

2 min read; 8 GFI

I knew it was too good to be true. While a little bit of me hoped it was going to happen this time, mostly I was expecting it to not happen.

It didn't happen.

Today was the day when Openreach were supposed to turn up again and deliver me a full fibre connection. The engineer was booked to turn up some time between 08:00 and 13:00 (as before). I was ready at 08:00. I was ready before 08:00 if I'm honest.

By 12:00 there was no sign of them. Despite there being an hour left to go, I'd written them off as a no-show again. I was wrong this time though. There was a knock on the door about 10 minutes later.

The engineer introduced himself, said he needed to go for a walk around first to get a feel for how and where the work needed to happen, and to figure out where the fibre was to come from (I kind of feel like this would be the sort of thing they'd know up front, but it's not my job and I trust them to know it).

Another 5 minutes and he's back... to tell me they can't do the job because the pole the fibre needs to come from is too far away. O_o

Now, I'm not going to get annoyed at this chap; presumably someone should have done some sort of site survey beforehand. Presumably this was the sort of thing that should have happened before the previous attempt to deliver the product?

So now I'm still without fibre, but with part of the job done. He installed the wee box that goes inside the house, and also the wee box that goes on the outside of the house. Of course, he drilled a hole and hooked them both up. So now I'm down an electrical socket, but have gained a box with a little red light that tells me I don't have full fibre.

He left assuring me that, having done this, it ensures that the actual delivery of the cable is turned into a priority. I can't say I'm that convinced, having sort of been here before. Some time later I got this text message:

We're sorry we couldn't get you connected today. The job is a bit more complex than usual.

We are going to get it sorted though and promise Full Fibre's worth the wait. We'll be back in touch in the next few days.

Again, I'm not convinced, having sort of been here before.

If I was a little more cynical and a little more prone to seeing a conspiracy where there was just a cock-up, I'd almost be tempted to entertain the idea that they turned up and fitted the box knowing full well that there was no fibre to be hooked up. Doing half a job is starting the job, after all. Presumably on some sheet somewhere that looks better than failing to do the job a second time.

I'm going to give them a couple of days to get back to me, as per the message, and then I think it's time to chase up EE and ask why, once again, they've failed to deliver me a product they promised me was available.

Rogallo v0.6.0

3 min read; 11 GFI

I've just released Rogallo v0.6.0, which contains the last big feature that was missing to make it a viable daily-driver Gemini Protocol client. That feature? Client certificates.

From now on, if you visit a capsule that requests a client certificate, rather than an error being shown, a dialog will pop up:

Simple dialog

When you select the Create button, the certificate will be created and then, from then on, when you visit the capsule, that client certificate will be used.

As you might have noticed, there are "advanced options" available too. Most are just optional values that go into the certificate itself:

The advanced options

The two advanced options that mostly affect how all of this works are the scope and the transient option. The transient option means that the certificate is only good for the lifetime of this run of Rogallo. If you close Rogallo, the certificate will be discarded. In almost all cases, you'll want to leave this turned off.

The scope toggle affects the scoping of the certificate. As I've been able to understand, the strict reading of the Gemini Protocol says that a certificate should be scoped to the host, port, and path where it was first requested and generated for. However, out in the real world, it seems there are applications built for the protocol that don't work well with that approach. With this in mind, I've built Rogallo to always scope to just the domain and port, by default. If you want a particular certificate to follow the strict letter of the specification, turn the "Scope to domain/port" option off.

With all that in place, it should now be possible to use Rogallo with any Gemini application that needs client-side authentication. For the last couple of days, I've been using it to successfully play AstroBotany, for example.

Logged in to AstroBotany

As I said: with this in place, I believe Rogallo has all of the basic requirements of a Gemini protocol client covered. I'm not quite ready to call it v1.0.0 just yet -- there's a fair bit of testing and tweaking I still want to do, and I can see that, when it comes to certificates for example, there's some extra error handling I need to throw in. Additionally, the "advanced" version of the certificate create dialog is kind of tall for many terminals; I think I might need to play with the layout a bit.

Also, as I've mentioned a few times: I want to get proper documentation written and hosted on a dedicated site.

Back to this release: there's also a handful of other QoL changes and fixes. These include:

  • Any page that is opened from an in-page link is now always retrieved from the remote location, bypassing any cached copy. The idea being that, if someone is actively navigating documents, they will want the freshest version of the new page.
  • Fixed the layout of list items. Before now, the text wasn't wrapping, while, at the same time, space was being made for the text as if it was being wrapped.
  • The bookmark search palette is no longer available if there are no bookmarks to search (the idea being that not being available is less confusing than being available but empty).
  • The connection timeout, read timeout, and maximum number of redirects can now be set in the configuration file.
  • The title area of the viewer now has a key icon that appears if a page is using a client certificate.
  • Pages that require a client-side certificate are never added to the cache (the idea being that such pages are more likely to have dynamic content, and so the freshest version should always be loaded).
  • Reworked what is recorded in navigation and location history to ensure that what is saved is the landing URI, not the URI that was first visited. This solves the problem of what happens during redirections, and so also solves the issue of what happens with 10/11 response inputs (having the resulting query appear in history could result in duplicated "submissions" to whatever app was in use).

With these enhancements and fixes in place, I'm going to keep tending my plant, and posting away on Station, as a way of continuing to shake down the application. With that in mind, if anyone knows of any other sites and apps I should be testing against out in Geminispace, do let me know!

Wasat v0.4.0

2 min read; 10 GFI

By this point today I was hoping to have released a new version of Rogallo, complete with client certificate support. It is more or less all there and ready to go, but I ran into a small problem, something which confused me.

You see, according to the documentation for the Gemini Protocol, when there's a request by a capsule for a client certificate, that certificate should be scoped to the host, port and path and all paths below it. So that means that if example.com/foo causes a certificate to be requested, it's good for example.com/foo and example.com/foo/bar, but it isn't valid for example.com/other.

Makes sense.

The problem I ran into pretty quickly, with my implementation of this in Wasat and Rogallo, was this: I hit a site (a microblogging site of sorts) that had a joining page at example.com/join. Once you joined up and set your user name, you'd normally land at example.com/me. They're sibling paths and so should not use the same certificate. However, this was done via redirection, so I did some work to "clone" a certificate when there's a redirection.

But then it got more complicated. The site also lets you follow other people. This means that if you visit example.com/other-user you should also still have the client certificate in place so the capsule knows who you are (because client certificates are also, in effect, session cookies, as I understand it), so you can perform the follow. Again, this is a sibling path, and there's no redirection, so the certificate is no good because, at this point, it's scoped to example.com/join and example.com/me.

Meanwhile: testing this with Lagrange, it had no such problem whatsoever. How was it getting around this issue? Was I doing something wrong? Was I misreading the specification for the protocol? Was Lagrange being a bit more relaxed about its certificate scope?

After doing some digging, it would seem that it's the latter. It looks like it, and perhaps other clients, take a pragmatic approach to certificate scopes and generally scope them to the host and port alone, ignoring the path (in the case of Lagrange it seems to sort of actually divorce the certificates from the URIs anyway, treating certificates more as identities you can associate with any capsule, etc).

Given this, at least for now, I'm going to take that approach. Any time a certificate needs to be generated in Rogallo, I'm going to give the user the option (on by default) to scope the certificate to the whole host/port combination. Later on I might add the ability to fully manage certificates (right now that can be done by editing the certificates file in the data directory, but a proper UI for it would be nice).

Which brings me to this release of Wasat. v0.4.0 adds some extra functionality to GeminiURI that allows changing and removing individual parts of the URI. There's a new replace method that can be used to create a clone of a URI with various parts changed. Also, if you just want to change one specific part or simply prefer method chaining approaches, I've also added more with_ methods similar to the pre-existing with_query method, so now there's also with_host, with_port and with_path.

With these in place I can go back to Rogallo and carry on with the last bits of work I want to do on client certificate support, with Wasat making it easy for me to clone up and chop and change URIs to suit the scoping requirements.

Wasat v0.3.0

1 min read; 11 GFI

Wasat v0.3.0 is now available. This is a pretty small update, but one that's going to be useful in the next release of Rogallo. I've now got client certificate support up and going in the application, and I thought it might be useful to show the user if a given page is using a client certificate or not (and, perhaps, at some point, make the details of the certificate available as part of some page information dialog).

With this in mind, I've added client_cert_path and client_cert_used properties to the Response class. The former is the path to the certificate used (if one was used), the latter is a simple boolean flag to say if a certificate was used at all.

Of course, client_cert_path could be used for both purposes as it'll be None if one isn't used, but client_cert_used will read better in code if that's all that's needed.

Wasat v0.2.0

1 min read; 10 GFI

I've made a quick update to Wasat, my async Gemini Protocol client library for Python. Now that I'm at a point where I want to add client certificates to Rogallo, I'm essentially shaking down the support for this in Wasat.

One thing I wanted right away was a certificate that, in effect, never expires. So with this release of Wasat I've added an option where the days to expire can be set to None, which results in the expiration date being set to 9999-12-31.

Rogallo v0.5.0

4 min read; 11 GFI

As mentioned in the last release, I've been afk for a week and a bit, enjoying some downtime over in the Netherlands. Although... it wasn't exactly all afk. I did take a keyboard with me and, while time permitted, I did tinker on Rogallo. That's resulted in quite a few TODO items being ticked off, and quite a few changes and improvements being made.

Visible MIME type

It's a small tweak, but I found it useful. The status bar of the main viewer panel now shows the MIME type of the document currently being viewed. Normally it will be showing text/gemini:

text/gemini

but Rogallo can show some other text/ types too, so this will also make it obvious what you're looking at:

text/plain

You might also notice that, depending on the theme being used, the "correct" MIME type gets a "this is fine" colour whereas anything else is in a more "neutral" colour.

Better handling of text/plain and friends

Now, if a document comes in that isn't text/gemini, there is no attempt to parse and render it as Gemtext; it's just shown as a simple block of plain text.

MIME type handling of local files

Given the above changes, Rogallo now makes an effort to guess the MIME type of any local file you view. This should help ensure that only Gemtext files get parsed and rendered as such.

OS hand-off for other MIME types

Where possible, when confronted with a MIME type that Rogallo can't handle, it will attempt to hand it off to your environment's main web browser. While not ideal, I have no wish to turn Rogallo into a terminal-based general content browser/viewer; this is all about Gemini and Gemtext.

History enhancements

The history list has been updated to allow the removal of individual items, and also clearing down the whole history.

Added home page support

It's now possible to set a home page with either a SetHome (which prompts for a URI) or a SetHomeToCurrentLocation (it does what it says) command. There is also a GoHome command that takes you to the home page you've set. The default bindings for all of these can be found by either running rogallo bindings, or by viewing the help screen; pulling up the command palette is also an option.

Added support for bookmarks

Bookmarks are now supported. The ToggleBookmarks will show/hide the bookmarks list. AddLocationToBookmarks will add the current location to the bookmarks. SearchBookmarks lets you search the bookmarks.

More command line suggestions

The completion suggestion facility in the application's command line (where you enter URIs or commands) has been enhanced to include suggestions from the navigation history, the location visit history and the bookmarks. This should make it a little easier to enter a URI you're trying to remember.

Having added the SearchBookmarks command, it made sense to also add a SearchHistory command too. So with that you can quickly search all the locations you've visited (within the limits of the history) and head back to one.

Optimised Gemtext rendering

While not something that should generally be obvious to the user, the Gemtext rendering engine has been optimised a little to reduce the number of Textual widgets used to display a document by consolidating all adjacent plain paragraphs.

Cleaned up quoted paragraphs

I've cleaned up an issue with adjacent quoted paragraphs. Until now there was an empty line between each quote; this spoiled the layout.

View source and ANSI escape sequences

Some Gemini sites use ANSI escape sequences to add colour to pages. While this isn't, as far as I can tell, part of the standard for Gemtext, it's a simple thing to support and so Rogallo has supported rendering this for a while; if a page has colours, they'll be used.

This meant that if you asked to view the source of a page, you'd also see that rendered in colour. I felt that wasn't in the spirit of viewing the source.

So now, if viewing a page like this:

My glower

When you go to view the source, instead of all of the colours still being rendered, you now get to see which ANSI escape codes were used where:

ANSI source

Viewer auto-focus

One small change is that, any time a document is loaded (from bookmarks, history, the command line, etc), the viewer now gains focus. Something I kept forgetting to do and finally I got fed up with having to tab over to the viewer each time.

Content cache

Rogallo now has a content cache for pages loaded from capsules (the aim is to never bother caching content loaded from the filesystem). Any page that is loaded with a success status code (20) gets cached, and when you go back to it, if it's within the TTL of the cache entry (by default set to one hour), the content of the page will be loaded from the cache rather than making a fresh request.

Using the Reload command always bypasses the cache.

There is also a ClearCache command which will delete all cached data.

The TTL of the cache can be changed in the configuration file by updating the value for cache_ttl. Also, if you don't wish to ever use a cache, you can set with_cache to false to disable it.

What's next

With all of the above, I feel this gets Rogallo close to being v1.0.0-ready. Not quite, but very close. The main addition that still needs to be tackled is client-side certificates. I don't anticipate this being too tricky, it's just more a case of needing to play around with the code I've got so far, and needing to think about how to implement it in a TUI-friendly way (if, indeed, there are any considerations there at all).

For now though, as long as you don't need a client-side certificate, there's plenty to play with and try out.

A view of Whitby

1 min read; 7 GFI

I'm back home, back in Scotland, after a touch over a week in the Netherlands. It's been a great week. Much like on the flight out, from the aircraft, I managed to get a view of a part of the UK I like. This time it was Whitby.

Whitby

While likely not immediately obvious, it is there. It was a lot more obvious with the naked eye. Zooming in a bit...

Whitby detail

The track confirms that we were in a good position for such a view:

Track of our flight

While I didn't grab a photo (I wasn't in a window seat this time so it wasn't so easy to keep track of where we were), I also managed to see Scarborough -- a place where I spent many summer holidays as a child in the 1970s.

Sadly I did miss a view of Newcastle, as when we got close to there, we took a left-hand turn and all I could see out of our windows was sky.

Perhaps next time...

textual-enhanced v1.6.0

1 min read; 10 GFI

I've just made a small update to textual-enhanced, my core library used for most of my Textual-based applications. In v1.6.0 I've extended the "constructor" for ModalInput to allow passing in optional values for password, suggester, title and sub_title.

Most of the time I just want to quickly call on ModalInput to get input from the user. If I need anything more fancy, I roll my own dialog. But in some work I'm doing on Rogallo, it would be helpful for me to at least set the suggester. So, without adding every optional parameter for the Textual Input widget, I've extended what can be passed in to what I think will be a useful subset for my applications.

BagOfStuff v1.2.0

1 min read; 10 GFI

Quick bump to BagOfStuff. v1.2.0 adds something I totally forgot yesterday.

While adding the del method to the history classes, to make it easier for me to manipulate them as if they had the interface of a Python list, I totally forgot to add a clear method. Rogallo will need to be able to 100% clear history, as well as remove individual entries in the history, so that's kind of needed too.

It's there now.