I like to check in on my new caches after about a week in the field to ensure there are no teething troubles with their hiding place/weatherproofing etc. All looks good here!
As you might know if you were paying close attention in Summer 2019, I run a “URL
shortener” for my personal use. You may be familiar with public URL shorteners like TinyURL
and Bit.ly: my personal URL shortener is basically the same thing, except that only
I am able to make short-links with it. Compared to public ones, this means I’ve got a larger corpus of especially-short (e.g. 2/3 letter) codes available for my personal use. It also
means that I’m not dependent on the goodwill of a free siloed service and I can add exactly the features I want to it.
For the last nine years my link shortener has been S.2, a tool I threw together in Ruby. It stores URLs in a
sequentially-numbered database table and then uses the Base62-encoding of the primary key as the “code” part of the short URL. Aside from the fact that when I create a short link it shows me a QR code to I can
easily “push” a page to my phone, it doesn’t really have any “special” features. It replaced S.1, from which it primarily differed by putting the code at the end of the URL rather than as part of the domain name, e.g. s.danq.me/a0 rather than a0.s.danq.me: I made the switch
because S.1 made HTTPS a real pain as well as only supporting Base36 (owing to the case-insensitivity of domain names).
But S.2’s gotten a little long in the tooth and as I’ve gotten busier/lazier, I’ve leant into using or adapting open source tools more-often than writing my own from scratch. So this
week I switched my URL shortener from S.2 to YOURLS.
One of the things that attracted to me to YOURLS was that it had a ready-to-go Docker image. I’m not the biggest fan of Docker in general,
but I do love the convenience of being able to deploy applications super-quickly to my household NAS. This makes installing and maintaining my personal URL shortener much easier than it
used to be (and it was pretty easy before!).
Another thing I liked about YOURLS is that it, like S.2, uses Base62 encoding. This meant that migrating my links from S.2 into YOURLS could be done with a simple cross-database
INSERT... SELECT statement:
One of S.1/S.2’s features was that it exposed an RSS feed at a secret URL for my reader to ingest. This was great, because it meant I could “push” something to my RSS reader to read or repost to my blog later. YOURLS doesn’t have such a feature, and I couldn’t find anything in the (extensive) list of plugins that would do it for me. I needed to write my own.
I could have written a YOURLS plugin. Or I could have written a stack of code in Ruby, PHP, Javascript or
some other language to bridge these systems. But as I switched over my shortlink subdomain s.danq.me to its new home at danq.link, another idea came to me. I
have direct database access to YOURLS (and the table schema is super simple) and the command-line MariaDB client can output XML… could I simply write an XML
Transformation to convert database output directly into a valid RSS feed? Let’s give it a go!
I wrote a script like this and put it in my crontab:
mysql --xml yourls -e \"SELECT keyword, url, title, DATE_FORMAT(timestamp, '%a, %d %b %Y %T') AS pubdate FROM yourls_url ORDER BY timestamp DESC LIMIT 30"\
| xsltproc template.xslt - \
| xmllint --format - \
> output.rss.xml
The first part of that command connects to the yourls database, sets the output format to XML, and executes an
SQL statement to extract the most-recent 30 shortlinks. The DATE_FORMAT function is used to mould the datetime into
something approximating the RFC-822 standard for datetimes as required by
RSS. The output produced looks something like this:
<?xml version="1.0"?><resultsetstatement="SELECT keyword, url, title, timestamp FROM yourls_url ORDER BY timestamp DESC LIMIT 30"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"><row><fieldname="keyword">VV</field><fieldname="url">https://webdevbev.co.uk/blog/06-2021/perfect-is-the-enemy-of-good.html</field><fieldname="title"> Perfect is the enemy of good || Web Dev Bev</field><fieldname="timestamp">2021-09-26 17:38:32</field></row><row><fieldname="keyword">VU</field><fieldname="url">https://webdevlaw.uk/2021/01/30/why-generation-x-will-save-the-web/</field><fieldname="title">Why Generation X will save the web Hi, Im Heather Burns</field><fieldname="timestamp">2021-09-26 17:38:26</field></row><!-- ... etc. ... --></resultset>
We don’t see this, though. It’s piped directly into the second part of the command, which uses xsltproc to apply an XSLT to it. I was concerned that my XSLT
experience would be super rusty as I haven’t actually written any since working for my former employer SmartData back in around 2005! Back then, my coworker Alex and I spent many hours doing XML
backflips to implement a system that converted complex data outputs into PDF files via an XSL-FO intermediary.
I needn’t have worried, though. Firstly: it turns out I remember a lot more than I thought from that project a decade and a half ago! But secondly, this conversion from MySQL/MariaDB
XML output to RSS turned out to be pretty painless. Here’s the
template.xslt I ended up making:
<?xml version="1.0"?><xsl:stylesheetxmlns:xsl="http://www.w3.org/1999/XSL/Transform"version="1.0"><xsl:templatematch="resultset"><rssversion="2.0"xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Dan's Short Links</title><description>Links shortened by Dan using danq.link</description><link> [ MY RSS FEED URL ]</link><atom:linkhref=" [ MY RSS FEED URL ] "rel="self"type="application/rss+xml"/><lastBuildDate><xsl:value-ofselect="row/field[@name='pubdate']"/> UTC</lastBuildDate><pubDate><xsl:value-ofselect="row/field[@name='pubdate']"/> UTC</pubDate><ttl>1800</ttl><xsl:for-eachselect="row"><item><title><xsl:value-ofselect="field[@name='title']"/></title><link><xsl:value-ofselect="field[@name='url']"/></link><guid>https://danq.link/<xsl:value-ofselect="field[@name='keyword']"/></guid><pubDate><xsl:value-ofselect="field[@name='pubdate']"/> UTC</pubDate></item></xsl:for-each></channel></rss></xsl:template></xsl:stylesheet>
That uses the first (i.e. most-recent) shortlink’s timestamp as the feed’s pubDate, which makes sense: unless you’re going back and modifying links there’s no more-recent
changes than the creation date of the most-recent shortlink. Then it loops through the returned rows and creates an <item> for each; simple!
The final step in my command runs the output through xmllint to prettify it. That’s not strictly necessary, but it was useful while debugging and as the whole command takes
milliseconds to run once every quarter hour or so I’m not concerned about the overhead. Using these native binaries (plus a little configuration), chained together with pipes, had
already resulted in way faster performance (with less code) than if I’d implemented something using a scripting language, and the result is a reasonably elegant “scratch your
own itch”-type solution to the only outstanding barrier that was keeping me on S.2.
All that remained for me to do was set up a symlink so that the resulting output.rss.xml was accessible, over the web, to my RSS reader. I hope that next time I’m tempted to write a script to solve a problem like this I’ll remember that sometimes a chain of piped *nix
utilities can provide me a slicker, cleaner, and faster solution.
Update: Right as I finished writing this blog post I discovered that somebody had already solved this
problem using PHP code added to YOURLS; it’s just not packaged as a plugin so I didn’t see it earlier! Whether or not I
use this alternate approach or stick to what I’ve got, the process of implementing this YOURLS-database ➡ XML
➡ XSLT ➡ RSS chain was fun and
informative.
British motorists driving outside the UK must now remove old-style GB stickers or cover them up.
Instead they should display a UK sticker or have the UK identifier on their number plate.
The UK government guidance has been in place since Tuesday 28 September.
…
With the replacement of “GB” stickers with “UK” ones, I’ll soon be able to add another joke to my list of jokes that aged badly. I first read
this in a joke book when I was a kid:
A young man gets his first car and his younger sister comes to look at it. “What’s this ‘L’ sticker for?” she asks.
“It stands for ‘Learning’,” replies man, “Because I’m still having driving lessons.”
Some time later, after he’s passed his test, the man is preparing to take a trip to France with his friends. His sister points to a sticker on his car. “Does this ‘GB’ mean you’re
‘Getting Better’?”
My @FreshRSS installation is the first, last, and sometimes only place I go on the Internet. When a site doesn’t have a feed but I wish it
did, I add one using middleware (e.g. danq.me/far-side-rss).
The second of the caches in this series that I found in between errands, this afternoon, was probably the easiest, because the hiding place reminds me distinctly of one of my own hides! This one, though, enjoys some excellent Christmas theming, for which a FP is due. TFTC!
I’d picked this one out as an essential for this afternoon’s “between jobs” hunt, because it completes my Solar System Wonders
set. How pleased I was to find that through this cache a tree is properly – albeit sparsely – decorated. Thanks for this, my third and final cache of the day. I’ll be back to finish
the series next time I’m around here with time to spare, I’m sure!
Having “solved” all the puzzles some time ago I’m picking away at finding the caches in this series a few at a time, starting the other week, every time I happen to be passing nearby. I felt a little overlooked by nearby windows this drizzly afternoon but I needn’t have
engaged my stealth skills: the coordinates were spot on and I soon had the cache in my hand. TFTC.
In his latest video, Andrew provides a highly-accessible and slick explanation of all of the arguments against what3words that I’ve been making for
years, plus a couple more besides.
Arguments that he makes that closely parallel my own include that what3words addresses are (a) often semantically-ambiguous, (b) potentially offensive, (c) untranslatable (and their
English words, used by non-English speakers, exaggerates problem (a)), and (d) based on an aggressively-guarded proprietary algorithm. We’re of the same mind, there. I’ll absolutely be
using this video to concisely explain my stance in future.
Andrew goes on to point out two further faults with the system, which don’t often appear among my arguments against it:
The first is that its lack of a vertical component and of a mechanism for narrowing-down location more-specifically makes it unsuitable for one of its stated purposes of improving
addressing in parts of the developing world. While I do agree that what3words is a bad choice for use as this kind of addressing system, my reasoning is different, and I don’t entirely
agree with his. I don’t believe that what3words are actually arguing that their system should be used alone to address a letter. Even in those cases where a given 3m × 3m
square can be used to point to a single building’s entryway, a single building rarely contains one person! At a minimum, a “what3words”-powered postal address is likely to
specify the name of the addressee who’s expected to be found there. It also may require additional data impossible to encode in any standardisable format, and adding a vertical
component doesn’t solve this either: e.g. care-of addresses, numbered letterboxes, unconventional floor numbers (e.g. in tunnels or skybridges), door colours, or even maps drawn from memory onto envelopes have been used in
addressed mail in some parts of the world and at some times. I’m not sure it’s fair to claim that what3words fails here because every other attempt at a universal system would too.
Similarly, I don’t think it’s necessarily relevant for him to make his observation that geological movements result in impermanence in what3words addresses. Not only is this a
limitation of global positioning in general, it’s also a fundamentally unsolvable problem: any addressable “thing” is capable or movement both with and independent of the part
of the Earth to which it’s considered attached. If a building is extended in one direction and the other end demolished, or remodelling moves its front door, or a shipwreck is split
into two by erosion against the seafloor, or two office buildings become joined by a central new lobby between them, these all result in changes to the positional “address” of that
thing! Even systems designed specifically to improve the addressability of these kinds of items fail us: e.g. conventional postal addresses change as streets are renamed, properties
renamed or renumbered, or the boundaries of settlements and postcode areas shift. So again: while changes to the world underlying an addressing model are a problem… they’re not a
problem unique to what3words, nor one that they claim to solve.
One of what3words’ claimed strengths is that it’s unambiguous because sequential geographic areas do not use sequential words, so ///happy.adults.hand is nowhere near
///happy.adults.face. That kind of feature is theoretically great for rescue operations because it means that you’re likely to spot if I’m giving you a location that’s in
completely the wrong country, whereas the difference between 51.385, -1.6745 and 51.335, -1.6745, which could easily result from a transcription error, are an awkward 4 miles away. Unfortunately, as Andrew
demonstrates, what3words introduces a different kind of ambiguity instead, so it doesn’t really do a great job of solving the problem.
And sequential or at least localised areas are actually good for some things, such as e.g. addressing mail! If I’ve just delivered mail to 123 East Street and my next stop is
256 East Street then (depending on a variety of factors) I probably know which direction to go in, approximately how far, and possibly even what side of the road it’ll be on!
That’s one of the reasons I’m far more of a fan of the Open Location Code, popularised by Google as Plus Codes. It’s got many great features, including variable resolution (you can give a short code, or just the beginning of a code, to specify
a larger area, or increase the length of the code to specify any arbitrary level of two-dimensional precision), sequential locality (similar-looking codes are geographically-closer),
and it’s based on an open standard so it’s at lower risk of abuse and exploitation and likely has greater longevity than what3words. That’s probably why it’s in use for addresses
in Kolkata, India and rural Utah. Because they
don’t use English-language words, Open Location Codes are dramatically more-accessible to people all over the world.
If you want to reduce ambiguity in Open Location Codes (to meet the needs of rescue services, for example), it’d be simple to extend the standard with a check digit. Open Location Codes
use a base-20 alphabet selected to reduce written ambiguity (e.g. there’s no letter O nor number 0), so if you really wanted to add this feature you could just use a base-20
modification of the Luhn algorithm (now unencumbered by patents) to add a check digit, after a predetermined character at the
end of the code (e.g. a slash). Check digits are a well-established way to ensure that an identifier was correctly received e.g. over a bad telephone connection, which is exactly why we
use them for things like credit card numbers already.
Basically: anything but what3words would be great.
Having succeeded at my primary goal for the evening of finding the challenging sibling of this cache, Herbology, I realised I
probably had just enough time left before sunset to find this one, too, if I got a move on. As I ran along the path and rounded the corner to the field at the edge of which this cache
is found, though, I was in for a bit of a surprise!
I’ve joked to my partner that the deer in South Leigh seem to be suicidal, based on the frequency with which they will leap out in front of my
car or bike on the rare occasions that I pass through the village (I’ve avoided hitting any so far, but they keep trying to make me). Well today it was my turn to narrowly avoid being
run over, as a pair of large deer rushed out from the field and almost bowled me over! Perhaps now they’ll understand how startling it is to almost end up ploughing through a living
thing and avoid jumping out in front of me? Or perhaps not.
In any case, I quickly found the cache’s hiding place once I’d crossed the field, and I could have probably done it 10 minutes later if I’d needed to… but probably not much beyond that;
once the sun was gone my eyes wouldn’t have been up to it! As others have noted, this cache is in need of repair: I’m pretty sure it once must have fit the theme of its siblings but
right now it’s a cracked, open shell, miraculously still dry enough inside to sign the log but that’s probably only a matter of time. :-(
Anyway: thanks to the CO for a fun series and a delightful, if frantic, walk some of these Autumn evenings. TFTCaches!
I get precious little time for geocaching lately: between work, childcare, household and volunteering commitments it’s a challenge to squeeze in a quick expedition here and there.
That’s doubly-true as the days get shorter: after finishing work, feeding the children etc. it’s already starting to get dim, and caches that I
know will be more-challenging to find – like this D4.5! – become a race against time.
A fortunate side-effect of my unusual living arrangement is that I’m only needed for bathtime and bedtime story-reading duties two nights out of every
three, and so when this evening achieved the hat-trick of me not being on bedtime duty, not being urgently needed for work in the evening, and the weather looking good, I leapt
onto my bike to come and find this cache. I’d found its sibling Geology a fortnight ago without two much difficulty, but – knowing that Herbology
would be much harder! – I’d planned to come out and perform a dedicated search for this and this cache only this evening. I cycled to South Leigh and then up the old Barnard Gate road,
stopping at N 51° 46.366, W 001° 25.259′ to lock my bike to a wooden footbridge at the point at which a footpath crosses the road. From there, I jogged North up the path to find the
GZ (bringing my front bike light for use as a torch, should the need arise).
I had anticipated that a search would be needed and had a few ideas about the kinds of things I might be looking for, but when after approaching half an hour I’d found nothing at all
and had resorted to poking at candidate hiding places with a stick while I shone my torch around, I was worried that this expedition might be a bust. Swallowing my pride, I messaged the
CO to see if they might be able to provide a further hint. Amazingly, they were not only online but able to give a hint that pointed me at
exactly the kind of thing I ought to be hunting for… because it turned out I’d already moved the cache container while hunting elsewhere in its hiding place!
Upon returning this expertly-stealthy cache to its hiding place, I realised that I might just have time to find the third of this triplet, and so I took off at top speed for Zoology.
I am not saying Apple’s approach is wrong. What Apple is doing is important too, and I applaud the work Apple has been doing in improving privacy on the web.
But it can’t be the only priority. Just imagine what the web would look like if every browser would have taken that approach 20 years ago.
Actually, no, don’t imagine it all. Just think back at Internet Explorer 6; that is what the web looked like 20 years ago.
…
There can only be one proper solution: Apple needs to open up their App Store to browsers with other rendering engines. Scrap rule 2.5.6 and allow other browsers on
iOS and let them genuinely compete.
As a reminder, Safari is the only web browser on iOS. You might have been fooled to think otherwise by the appearance of other browsers
in the App Store or perhaps by last year’s update that made it
possible at long last to change the default browser, but it’s all an illusion. Beneath the mask, all browsers on iOS are powered by Safari’s WebKit, or else they’re booted
from the App Store.
Neils’ comparison to Internet Explorer 6 is a good one, but as I’ve long pointed out, there’s a big and important difference between Microsoft’s story during the First Browser War and
Apple’s today:
Microsoft bundled Internet Explorer with Windows, raising the barrier to using a different web browser, which a court ruled as monopolistic and recommended that Microsoft be broken into smaller companies (this recommendation
was scaled back on appeal).
Apple bundle Safari with iOS and prohibit the use of any other browser’s rendering engine on that platform, preventing the use of a different web browser. Third-party
applications have been available for iOS – except, specifically, other browser rendering engines and a handful of other things – for 13 years now, but it still seems unlikely we’ll see
an antitrust case anytime soon.
Apple are holding the Web back… and getting away with it.
A quick almost-CnD on the school run. I’d love to come back and do the series someday! Found easily (although the hint object is nowhere
in sight!), but container was challenging to open! Luckily the edge of the carabiner I use to clip my GPSr to my belt was up to the task!
TFTC.
“Solved” all the puzzles some time ago, then came out to find this cache as a drive-by (on the minor, not the major, nearby road, of course!)
while in-between other errands nearby. Was looking for something smaller when I laid my hands on the cache container, which I thought looked “out of place”, but the weight balance of
the thing I’d picked up felt wrong… like something was loose inside? That’s when I realised I was holding the cache! Signed log and returned it to its spot. TFTC.
Unsurprisingly my checkins, which represent #geocaching/#geohashing activity,
grow in the spring and peak in the summer when the weather’s better!
At first I assumed the notes peak in November might have been thrown off by a single conference, e.g. musetech, but it turns out I’ve
just done more note-friendly things in Novembers, like Challenge Robin II and my Cape Town
meetup, which are enough to throw the numbers off.