|
|
|
@ -0,0 +1,228 @@
|
|
|
|
|
FORMATTING
|
|
|
|
|
Structured Gopher space(s) can be created with geomyidae through the use
|
|
|
|
|
of special indexing files of the form <name>.gph which, if present,
|
|
|
|
|
geomyidae uses to format and/or filter the contents of the base directory
|
|
|
|
|
(/var/gopher by default) and create gopher menus. However, index files
|
|
|
|
|
are not required: if no index.gph, index.cgi or index.dcgi file is found,
|
|
|
|
|
geomyidae simply lists the directory contents in alphanumeric order. In
|
|
|
|
|
addition, a directory can utilize multiple index files to create a
|
|
|
|
|
layered gopher environment without the use of sub-directories: ie.
|
|
|
|
|
pictures.gph, music.gph, documents.gph could be "directories" within
|
|
|
|
|
main.gph, yet all reside in /var/gopher along with their respective files
|
|
|
|
|
(*.jpg, *.mp3, *.pdf for example).
|
|
|
|
|
|
|
|
|
|
Anatomy of an index.gph file
|
|
|
|
|
In general, each line of an index.gph file has the following structure:
|
|
|
|
|
|
|
|
|
|
[<type>|<desc>|<path>|<host>|<port>]
|
|
|
|
|
|
|
|
|
|
where,
|
|
|
|
|
|
|
|
|
|
<type> = A valid gopher Item Type.
|
|
|
|
|
|
|
|
|
|
Some common Gopher Types as defined in RFC 1436 :
|
|
|
|
|
|
|
|
|
|
0 Item is a file
|
|
|
|
|
1 Gopher directory
|
|
|
|
|
3 Error
|
|
|
|
|
7 Item is an Index-Search server.
|
|
|
|
|
8 Item points to a text-based telnet session.
|
|
|
|
|
9 Binary file. Client reads until TCP connection closes!
|
|
|
|
|
g GIF format graphics file.
|
|
|
|
|
I Indeterminate image file. Client decides how to display.
|
|
|
|
|
|
|
|
|
|
In addition, geomyidae provides these:
|
|
|
|
|
|
|
|
|
|
h Item is a hypertext (HTTP) link
|
|
|
|
|
i Informational Item (used for descriptive purposes)
|
|
|
|
|
|
|
|
|
|
Unknown file types default to Type "9" (binary).
|
|
|
|
|
|
|
|
|
|
<desc> = description of gopher item. Most printable characters
|
|
|
|
|
should work.
|
|
|
|
|
|
|
|
|
|
<path> = full or relative path to gopher item (base value is "/" ).
|
|
|
|
|
Use the "Err" path for items not intended to be served.
|
|
|
|
|
|
|
|
|
|
<host> = hostname or IP hosting the gopher item. Must be resolvable
|
|
|
|
|
for the intended clients. If this is set to "server" , the server's
|
|
|
|
|
hostname is used.
|
|
|
|
|
|
|
|
|
|
<port> = TCP port number (usually 70) If this is set to "port" ,
|
|
|
|
|
the default port of the server is used.
|
|
|
|
|
|
|
|
|
|
Note: geomyidae doesn't require "informational" text to be formally Typed
|
|
|
|
|
as "[i|...]"; any line not beginning with "[" is treated as
|
|
|
|
|
informational, greatly simplifying the formatting of index.gph files.
|
|
|
|
|
However, if a line begins with a "t", this "t" is left out. This quirk
|
|
|
|
|
is there to allow "informational" text lines beginning with a "[" to
|
|
|
|
|
display. For dynamically generated index files it may be desirable to
|
|
|
|
|
either formally Type informational text or run it through a filter to add
|
|
|
|
|
a second "t" - .ie sed 's/^t/&&/' .
|
|
|
|
|
|
|
|
|
|
Note 2: You can escape a pipe ("|") character in for example a <desc>
|
|
|
|
|
field by prepending a slash ("\").
|
|
|
|
|
|
|
|
|
|
Note 3: The gph parser is very forgiving. If the link structure is not
|
|
|
|
|
parsed correctly, then the original line is printed.
|
|
|
|
|
|
|
|
|
|
index.gph Example
|
|
|
|
|
A root.gph file for a server running on host=frog.bog, port=70. Note use
|
|
|
|
|
of optional [i]nformational Item (line 2) for vertical space insertion:
|
|
|
|
|
|
|
|
|
|
Welcome to Frog.bog
|
|
|
|
|
[i||Err||]
|
|
|
|
|
[0|About this server|about.txt|frog.bog|70]
|
|
|
|
|
[0|Daily Log|/dtail.cgi|frog.bog|70]
|
|
|
|
|
[1|Phlog: like a blog, but not|/PHLOG|frog.bog|70]
|
|
|
|
|
[9|Some binary file|widget.exe|frog.bog|70]
|
|
|
|
|
[I|Snowflake picture|snowflake.jpg|frog.bog|70]
|
|
|
|
|
ttry our snowflakes!
|
|
|
|
|
|
|
|
|
|
Links and Searches
|
|
|
|
|
[1|Go to R-36.net|/|gopher.r-36.net|70]
|
|
|
|
|
[h|Go to NetBSD.org|URL:http://netbsd.org|frog.bog|70]
|
|
|
|
|
[7|Query US Weather by Zipcode|/weather.cgi?|frog.bog|70]
|
|
|
|
|
[7|Search Veronica II|/v2/vs|gopher.floodgap.com|70]
|
|
|
|
|
[8|Telnet to SDF Public Access Unix System|null|freeshell.org|23]
|
|
|
|
|
|
|
|
|
|
The above looks something like this in a text-based gopher client:
|
|
|
|
|
|
|
|
|
|
Welcome to Frog.bog
|
|
|
|
|
|
|
|
|
|
(FILE) About this server
|
|
|
|
|
(FILE) Daily Log
|
|
|
|
|
(DIR) Phlog: like a blog, but not
|
|
|
|
|
(BIN) Some binary file
|
|
|
|
|
(IMG) Snowflake picture try our snowflakes!
|
|
|
|
|
|
|
|
|
|
Links and Searches
|
|
|
|
|
(DIR) Go to R-36.net
|
|
|
|
|
(HTML) Go to NetBSD.org
|
|
|
|
|
(?) Query US Weather by Zipcode
|
|
|
|
|
(?) Search Veronica II
|
|
|
|
|
(TEL) Telnet to SDF Public Access Unix System
|
|
|
|
|
|
|
|
|
|
DYNAMIC CONTENT (gopher CGI)
|
|
|
|
|
There are two options provided for dynamic content creation: standard CGI
|
|
|
|
|
( .cgi ) and dynamic CGI ( .dcgi ). Despite the names, both can accept
|
|
|
|
|
input and generate dynamic content; the only difference is the latter re-
|
|
|
|
|
formats it's output so it appears to the server as a standard geomyidae
|
|
|
|
|
index (.gph) file. This makes the creation of on-the-fly gopher
|
|
|
|
|
directories much easier (see examples). All scripts must be under the
|
|
|
|
|
gopher root directory and be executable by the same user:group running
|
|
|
|
|
geomyidae. Consequently, it is best to use the -u and -g server options
|
|
|
|
|
to avoid running as root.
|
|
|
|
|
|
|
|
|
|
Both .cgi and .dcgi scripts have the same argument call structure (as
|
|
|
|
|
seen by geomyidae):
|
|
|
|
|
|
|
|
|
|
executable.[d]cgi $search $arguments $host $port
|
|
|
|
|
|
|
|
|
|
where
|
|
|
|
|
|
|
|
|
|
search = query string (type 7) or "" (type 0)
|
|
|
|
|
arguments = string after "?" in the path or ""
|
|
|
|
|
host = server's hostname ("localhost" by default)
|
|
|
|
|
port = server's port ("70" by default)
|
|
|
|
|
|
|
|
|
|
All terms are tab-separated (per gopher protocol) which can cause some
|
|
|
|
|
surprises depending on how a script is written. See the CGI file
|
|
|
|
|
(included in the geomyidae source archive) for further elaboration.
|
|
|
|
|
|
|
|
|
|
QUIRK: The original gopher client tried to be too intelligent. It is
|
|
|
|
|
using gopher+ when you request some resource. When "search" is just the
|
|
|
|
|
value "+", "!", "$" or empty, geomyidae will display a gopher+ redirect
|
|
|
|
|
instead of invoking the script. Be careful to design your search script
|
|
|
|
|
so the user is unlikely to enter those values. The designers of gopher+
|
|
|
|
|
did not think of classic gopher to survive. It survived gopher+.
|
|
|
|
|
|
|
|
|
|
Additionally to the above arguments several environment variables are
|
|
|
|
|
set.
|
|
|
|
|
|
|
|
|
|
GATEWAY_INTERFACE = `CGI/1.1'
|
|
|
|
|
PATH_INFO = script which is executed
|
|
|
|
|
PATH_TRANSLATED = absolute path with script which is executed
|
|
|
|
|
QUERY_STRING = arguments (See above.)
|
|
|
|
|
REMOTE_ADDR = IP of the client
|
|
|
|
|
REMOTE_HOST = REMOTE_ADDR
|
|
|
|
|
REQUEST_METHOD = `GET'
|
|
|
|
|
SCRIPT_NAME = script which is executed
|
|
|
|
|
SERVER_NAME = server's hostname
|
|
|
|
|
SERVER_PORT = server's port
|
|
|
|
|
SERVER_PROTOCOL = `gopher/1.0'
|
|
|
|
|
SERVER_SOFTWARE = `geomyidae'
|
|
|
|
|
X_GOPHER_SEARCH = search (See above.)
|
|
|
|
|
|
|
|
|
|
Some CGI Examples
|
|
|
|
|
Note: these are a very simple examples with no fitness checks with
|
|
|
|
|
respect to safety/security.
|
|
|
|
|
|
|
|
|
|
ex. uptime.cgi - standard CGI, no queries
|
|
|
|
|
|
|
|
|
|
#!/bin/sh
|
|
|
|
|
# uptime.cgi - prints system uptime(1)
|
|
|
|
|
/usr/bin/uptime
|
|
|
|
|
exit 0
|
|
|
|
|
|
|
|
|
|
Call the above with the following index.gph entry:
|
|
|
|
|
|
|
|
|
|
[0|System Uptime|/uptime.cgi|frog.bog|70]
|
|
|
|
|
|
|
|
|
|
A search query request must have an item Type of "7" to be called from an
|
|
|
|
|
index.gph file. It also needs a "?" suffix in the <path> field:
|
|
|
|
|
|
|
|
|
|
ex. hello.cgi - standard CGI with query
|
|
|
|
|
|
|
|
|
|
#!/bin/sh
|
|
|
|
|
# hello.cgi - welcome user
|
|
|
|
|
NAME=$1
|
|
|
|
|
HOSTNAME=$2
|
|
|
|
|
echo ""
|
|
|
|
|
echo Hello $NAME - welcome to $HOSTNAME
|
|
|
|
|
exit 0
|
|
|
|
|
|
|
|
|
|
Call the above with the following index.gph entry:
|
|
|
|
|
|
|
|
|
|
[7|Hello You - Please enter your
|
|
|
|
|
name|/hello.cgi?FROG.bog|frog.bog|70]
|
|
|
|
|
|
|
|
|
|
And do a simple snarf(1) query (note the inserted TAB):
|
|
|
|
|
|
|
|
|
|
% snarf "gopher://frog.bog/7/hello.cgi?FROG.bog[TAB]Christoph" -
|
|
|
|
|
Hello Christoph - welcome to FROG.bog
|
|
|
|
|
|
|
|
|
|
Dynamic CGI entries are similar to above except that the script needs to
|
|
|
|
|
create output as described in the FORMATTING section:
|
|
|
|
|
|
|
|
|
|
ex. jughead.dcgi - dynamic CGI script with query
|
|
|
|
|
|
|
|
|
|
#!/bin/sh
|
|
|
|
|
# jughead.dcgi - jughead-like local gopher search
|
|
|
|
|
KWRD="$1"
|
|
|
|
|
ARCHIVE="/var/gopher/textfiles/"
|
|
|
|
|
echo "[i|Search results for \"${KWRD}\":|Err||]"
|
|
|
|
|
echo "[i||Err||]"
|
|
|
|
|
# grep(1) recursive, case-insensitive KWRD search of ARCHIVE:
|
|
|
|
|
for RESULT in $(/usr/bin/grep -i -l -m1 ${KWRD} -r $ARCHIVE)
|
|
|
|
|
do
|
|
|
|
|
DESC=$(/usr/bin/basename ${RESULT})
|
|
|
|
|
PATH=$(echo "$RESULT" | /usr/bin/sed 's/^\/var\/gopher//')
|
|
|
|
|
echo "[0|${DESC}|${PATH}|frog.bog|70]"
|
|
|
|
|
done
|
|
|
|
|
exit 0
|
|
|
|
|
|
|
|
|
|
Call the above with the following index.gph entry:
|
|
|
|
|
|
|
|
|
|
[7|Search this Gopher|/jughead.dcgi?|frog.bog|70]
|
|
|
|
|
|
|
|
|
|
A successful query might look like this:
|
|
|
|
|
|
|
|
|
|
Search results for "fubar":
|
|
|
|
|
|
|
|
|
|
(FILE) How_Things_Break.txt
|
|
|
|
|
(FILE) Origins_of_Words.txt
|
|
|
|
|
(FILE) Phrases_of_the_Ages.txt
|
|
|
|
|
|
|
|
|
|
Care should to be exercised to avoid creating miss-Typed entries,
|
|
|
|
|
unwanted recursions, and/or unintended writes in the working directory.
|