You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
Go to file
chris west 5b02ccc1db chore: Release phd version 0.1.15 1 year ago
.cargo let linker strip release binaries 4 years ago
.github/workflows update gh actions 1 year ago
doc Default to dual stack and add BIND arg 4 years ago
img brighter 4 years ago
src update alphanumeric-sort dependency 1 year ago
tests/sort include fixture dir 4 years ago
.gitignore skeleton 4 years ago
CHANGELOG.md chore: Release phd version 0.1.15 1 year ago
Cargo.lock chore: Release phd version 0.1.15 1 year ago
Cargo.toml chore: Release phd version 0.1.15 1 year ago
LICENSE add license 4 years ago
Makefile basic manpage 4 years ago
README.md chore: Release phd version 0.1.15 1 year ago
header.gph center logo 4 years ago

README.md



phd is a small, easy-to-use gopher server.

Point it at a directory and it'll serve up all the text files, sub-directories, and binary files over Gopher. Any .gph files will be served up as gophermaps and executable .gph files will be run as a program with their output served to the client, like the glorious cgi-bin days of yore!

~ special files ~

  • header.gph: If it exists in a directory, its content will be shown above the directory's content. Put ASCII art in it.
  • footer.gph: Same, but will be shown below a directory's content.
  • index.gph: Completely replaces a directory's content with what's in this file.
  • ??.gph: Visiting gopher://yoursite/1/dog/ will try to render dog.gph from disk. Visiting /1/dog.gph will render the raw content of the .gph file.
  • .reverse: If this exists, the directory contents will be listed in reverse alphanumeric order. Useful for phloggin', if you date your posts.

Any line in a .gph file that doesn't contain tabs (\t) will get an i automatically prefixed, turning it into a Gopher information item.

For your convenience, phd supports geomyidae syntax for creating links:

This is an info line.
[1|This is a link|/help|server|port]
[h|URL Link|URL:https://noogle.com]

server and port will get translated into the server and port of the actively running server, eg localhost and 7070.

Any line containing a tab character (\t) will be sent as-is to the client, meaning you can write and serve up raw Gophermap files too.

~ dynamic content ~

Any .gph file that is marked executable with be run as if it were a standalone program and its output will be sent to the client. It will be passed three arguments: the query string (if any), the server's hostname, and the current port. Do with them what you will.

For example:

$ cat echo.gph
#!/bin/sh
echo "Hi, world! You said:" $1
echo "1Visit Gopherpedia	/	gopherpedia.com	70"

Then:

$ gopher-client gopher://localhost/1/echo?something
[INFO] Hi, world! You said: something
[LINK] Visit Gopherpedia

Or more seriously:

$ cat figlet.gph
#!/bin/sh
figlet $1

then:

$ gopher-client gopher://localhost/1/figlet?hi gopher
[INFO]  _     _                     _
[INFO] | |__ (_)   __ _  ___  _ __ | |__   ___ _ __
[INFO] | '_ \| |  / _` |/ _ \| '_ \| '_ \ / _ \ '__|
[INFO] | | | | | | (_| | (_) | |_) | | | |  __/ |
[INFO] |_| |_|_|  \__, |\___/| .__/|_| |_|\___|_|
[INFO]            |___/      |_|

~ ruby on rails ~

sh is fun, but for serious work you need a serious scripting language like Ruby or PHP or Node.JS:

$ cat sizes.gph
#!/usr/bin/env ruby

def filesize(file)
    (size=File.size file) > (k=1024) ? "#{size/k}K" : "#{size}B"
end

puts "~ file sizes ~"
spaces = 20
Dir[__dir__ + "/*"].each do |entry|
    name = File.basename entry
    puts "#{name}#{' ' * (spaces - name.length)}#{filesize entry}"
end

Now you can finally share the file sizes of a directory with the world of Gopher!

$ phetch -r 0.0.0.0:7070/1/sizes
i~ file sizes ~	(null)	127.0.0.1	7070
iCargo.toml          731B	(null)	127.0.0.1	7070
iLICENSE             1K	(null)	127.0.0.1	7070
iMakefile            724B	(null)	127.0.0.1	7070
itarget              288B	(null)	127.0.0.1	7070
iphd                 248K	(null)	127.0.0.1	7070
iCargo.lock          2K	(null)	127.0.0.1	7070
iREADME.md           4K	(null)	127.0.0.1	7070
img                 96B	(null)	127.0.0.1	7070
isizes.gph           276B	(null)	127.0.0.1	7070
isrc                 224B	(null)	127.0.0.1	7070

~ usage ~

Usage:

    phd [options] <root directory>

Options:

    -r, --render SELECTOR  Render and print SELECTOR to stdout only.
    -h, --host HOST        Hostname for links. [Default: {host}]
    -p, --port PORT        Port for links. [Default: {port}]
    -b, --bind ADDRESS     Socket address to bind to. [Default: {bind}]
    --no-color             Don't show colors in log messages.

Other flags:

    -h, --help      Print this screen.
    -v, --version   Print phd version.

Examples:

    phd ./path/to/site  # Serve directory over port 7070.
    phd -p 70 docs      # Serve 'docs' directory on port 70
    phd -h gopher.com   # Serve current directory over port 7070
                        # using hostname 'gopher.com'
    phd -r / ./site     # Render local gopher site to stdout.

~ installation ~

On macOS you can install with Homebrew:

brew install xvxx/code/phd

Binaries for Linux, Mac, and Raspberry Pi are available at gopher://phkt.io/1/releases/phd and https://github.com/xvxx/phd/releases:

Just unzip/untar the phd program into your $PATH and get going!

If you have cargo, you can install the crate directly:

cargo install phd --locked

~ development ~

cargo run -- ./path/to/gopher/site

~ resources ~

~ todo ~

  • systemd config, or something
  • TLS support
  • user input sanitization tests

~ status ~

phd is no longer under active development, but the latest version works great.