Blog indexRolling🥎blogPermalink

Doppio CGI examples

Jake Thoughts10 Sep 2021 23:02:35 -0400

One cannot easily understand how to use CGI with Doppio, a Gemini Server. Here I will provide some examples which may require input from a user. My language of choice is Perl but these examples should be trivial to translate into other languages. The `-T` flag indicates taint-mode and that Perl should do not allow unsafe interactions with user submitted data. You should do what ever the equivalent is for other languages.

The example yaml file suggests that `cgiDir` is absolute. This is wrong; it uses a relative path, so for me it is `cgi/`.

guestbook.cgi
#!/usr/bin/perl -T
use strict;
use warnings;

# Doppio expects header in this format
print "Content-Type: text/gemini\n\n"; 

open(my $fh, "<", "/path/to/guestbook.txt") or die "$0 cannot read guestbook.txt: $!";
while (my $line = <$fh>) {
        print $line;
}
close($fh);
print "=> ./sign.cgi Sign the guest book!";
sign.cgi
#!/usr/bin/perl -T
use strict;
use warnings;
use POSIX qw(strftime);

# checking to see if key has a value/exists (returns true or false)
if ($ENV{QUERY_STRING}) { 
        my $date = strftime "%b %e %Y", localtime;
        open(my $fh, '>>', "/path/to/guestbook.txt") or die "$0 cannot append guestbook.txt: $!";
		# write to file
                print $fh "$date: $EVN{QUERY_STRING}\n"; 
        close($fh);
	# Redirection for browsers
        print "Status 30\nContent-Type: ./guestbook.cgi\n\n"; 
} else {
	# Prompt user to give query
        print "Status 10\nContent-Type: What will you sign in the guest book?\n\n"; 
}
login.cgi
#!/usr/bin/perl -T
use strict;
use warnings;

# checking to see if key has a value/exists (returns true or false)
if ($ENV{REMOTE_USER}) { 
	# in case matching does not work
        my $remote_user = "47";  
        if ($ENV{REMOTE_USER} =~ m/,?CN=(.+),?) { # matching the common name
                $remote_user = $1;
        }
        print "Content-Type: text/gemini\n\n";
        print "# Welcome back, agent $remote_user!\n";
        # Maybe put a heredoc right here? Just an idea :)
} else {
	# Prompts the user to submit a cert.
        print "Status: 60\nContent-Type: Certificate (any) required."; 
}

Scripts that prompt the user to do something will run twice, so sign.cgi and login.cgi will run two times depending on what header (the first print) Doppio receives from them and will omit anything after.

Some advice... Most (all?) languages have environment varibles, so, maybe one could have a script print out each key and the value of each key so you know what you can work with. (a hint to search `x-programming-language environment variables`)

Additional advice... If you follow the OpenSSL instructions from Doppio's github page, I recommend setting `-days` (on the second command [it has `req` and `-x509`]) to a high number because it defaults at a low number which can be problematic for a protocol that TOFUs.


Other thoughts

Jake on 2021-09-11,04:06:44 said:

err... I should've mentioned this, Doppio version 0.7. Maybe future update changes things


Be sure to submit your thoughts! Emoji Ledger (hover mouse over)! Beware: emails are stored as plain text; botnets will pick it up.