💾 Archived View for tozip.chickenkiller.com › 2022-06-27-nofer-ann.gmi captured on 2022-07-16 at 13:55:07. Gemini links have been rewritten to link to archived content

View Raw

More Information

-=-=-=-=-=-=-

ANN: nofer - a gemini to gopher bridge

Created 2022-06-27

Gopher is OK, but it's an awkward protocol to write for. It has its quirks, to say the least. I do, however, particularly like seeing gopher pages that are left-and-right aligned. There's something just so neat about them.

I had been working on a Perl script called "nofer" ("no gopher") to work in conjunction with inetd on FreeBSD. It serves gmi pages as gopher pages, so if you have a Gemini capscule, you should be pretty much good to go. It is actually a shame that gopher has a weird layout. With the benefit of hindsight, we didn't really want to do it that way.

Without further ado, here's my nofer script:

#!/usr/bin/env perl
#toy gopher server - from gemini
# for setup on FreeBSD, see nopher.md

# settings that you may need to change
my $HOME = "/home/gemini";
my $LOG = "$HOME/tmp/nofer.log";
my $HOST = "\ttozip.chickenkiller.com\t70";
my $SRCROOT = "$HOME/repos/cerbo/website/gemini";

#use boolean;
use Cwd;
#use File::Spec;

my $request = <>;
$request =~ s/\r//g;
$request =~ s/\n//g;

if($request eq "") { $request = "index.gmi"; }
if($request eq "/") { $request = "index.gmi"; }

# check that client is not trying to snoop around our filesystem
my $path1 = "$SRCROOT/$request";
#my $can_path = File::Spec->canonpath($requested_path);
my $can_path = Cwd::abs_path($path1);
my $rascal = substr($can_path, 0, length($SRCROOT)) ne $SRCROOT;

if( $rascal || ! (-e $can_path)) {
        print "Error: File or directory not found!\n";
        exit 1;
}

open(FH, "<", "$can_path");

sub handle_mapfile {
        while(<FH>) {
                my $input = $_;
                $input =~ chomp $input;
                if( $_ =~ /^=>\s+(\S+)\s+(.*)/) {
                        my ($link, $text) = ($1, $2);
                        my $prefix = ($link =~ /.*\.gmi$/) ? "1" : "0"; # should probably need to classify link type
                        my $outtext = "$prefix$text\t/$link$HOST\r\n";
                        print $outtext;
                } else {
                        print "i$input\t\tnull.host\t1\r\n";
                }

        }
}

sub handle_nonmapfile {
        while(<FH>) { print "$_"; }
}

if($request  =~ m/\.gmi$/) {
        handle_mapfile ;
} else {
        handle_nonmapfile;
}


close FH;

open(FH, ">>", $LOG);
#my $dt = DateTime->now;
my $dt = localtime();
print FH "$dt:Request \"$request\"\n";
close FH;

#print $response;

It's not perfect by a long shot, but it's not so bad. It does the wrong thing when serving things like http and image requests. It also serves only static pages. Still, meh, it works well enough for me right now.

nofer script

I have written some installation notes for FreeBSD:

# nofer setup on FreeBSD

Perform static test:
./nofer
/

Install packages:
pkg install inetd
pkg install gopher

In /etc/services, add:
gopher7000      7000/tcp
gopher7000      7000/udp

In /etc/inetd.conf, add:
gopher  stream  tcp     nowait  gemini  /home/gemini/repos/cerbo/website/nofer  nofer
gopher7000      stream  tcp     nowait  gemini  /home/gemini/repos/cerbo/website/nofer  nofer


Activate inetd temporarily:
service inetd onestart


Test basic configuration:
gopher gopher://localhost:7000
gopher gopher://tozip.chickenkiller.com:7000
gopher gopher://localhost:70
gopher gopher://tozip.chickenkiller.com:70

This seems to work on port 70, which is a little odd, because I thought non-root users cannot use low port numbers.

Configure your router to redirect port 70 to your server.

Enable inetd permanently: in /etc/rc.conf, add:
inetd_enable="YES"

You'll need to adapt it to Linux, or whatever system it is you're using.

nofer.md configuration notes

I have set it up on my machine, and seems to work:

gopher://tozip.chickenkiller.com/

Hope that was of use.

So who wins the smallweb wars: gopher, or gemini?