knusbaum / cl-gopher

Gopher library in Common Lisp
6 stars 2 forks source link

cl-gopher

cl-gopher is a Common Lisp library for interacting with the Gopher protocol.

It is suitable for building both clients and servers, and provides a sample client.

cl-gopher has been tested and confirmed to work with:

Installation

cl-gopher is now available through quicklisp!

CL-USER> (ql:quickload 'cl-gopher)

If you want to use the source from this repo, rather than that distributed with quicklisp:

Make sure that the source is somewhere that asdf or quicklisp can find it. If you're not using quicklisp, consult the .asd file for required dependencies.

If you are using quicklisp, all dependencies should be available through it, and so automatically resolved.

CL-USER> (ql:quickload 'cl-gopher)
To load "cl-gopher":
  Load 1 ASDF system:
    cl-gopher
; Loading "cl-gopher"
[package cl-gopher].....
(CL-GOPHER)

Basic Usage

Note: This documentation assumes you know a bit about the gopher protocol, and doesn't cover the protocol's basic workings.

Most of the functions and classes have documentation strings attached to them. For better descriptions of the functions in the library, see that documentation.

Gopher Lines

The main class this library deals with is the GOPHER-LINE. A GOPHER-LINE represents a gopher menu item, (analogous to a html link)

GOPHER-LINE has a number of subclasses, depending on the type of the gopher link.

Lines can be created directly with MAKE-INSTANCE, by parsing gopher URIs with PARSE-GOPHER-URI, by reading lines from a stream (e.g. to a server speaking the gopher protocol) with READ-GOPHER-LINE, or by converting from an alist with GOPHER-LINE-FROM-ALIST.

Once you have a line, you have the ability to:

There are several other minor util functions that accept a GOPHER-LINE as an argument.

Contents

The other major class family in the library is the SELECTOR-CONTENTS class and subclasses. Instances of these classes are returned from GET-LINE-CONTENTS, and represent the various kinds of content that Gopher URIs can link to. The classes currently are:

All that is provided by the for working with contents objects are the slot accessors, and a generic function, DISPLAY-CONTENTS, which displays a contents object in human-readable format.

Quick Examples:

To get the contents of a gopher URI, Try the following:

CL-USER> (cl-gopher:display-contents
          (cl-gopher:get-line-contents 
           (cl-gopher:parse-gopher-uri "gopher://sdf.org/")))

cl-gopher includes a simple text browser client to exemplify the use of the library. You can test it with:

CL-USER> (cl-gopher:text-browser)
    Welcome to the SDF Public Access UNIX System .. est. 1987

    Official Site of the Internet Gopher Club Underground Syndicate

    We offer FREE and inexpensive memberships for people interested
    in the UNIX system and internetworking.  Personal GOPHERSPACE
    is available to all users as well as hundreds of UNIX utilities,
    games and networking utilities.  We are a federally recognized
    non-profit 501(c)7 organization and we are supported entirely
    by donations and membership dues.  ssh://sdf.org

11     SUBMENU SDF PHLOGOSPHERE (226 phlogs)
12     SUBMENU SDF GOPHERSPACE (1119 ACTIVE users)
13     SUBMENU SDF GOPHERSPACE (1371 AGED users)
14     SUBMENU SDF GOPHERSPACE (373 ANCIENT users)
15     SUBMENU SDF Frequently Asked Questions (FAQ)
16     SUBMENU SDF Accredited University Courses
17     SUBMENU Software and Documentation for various computers
18     SEARCH-LINE GopherSpace SEARCH Engine
19     SUBMENU Floodgap's GOPHERSPACE
    ____________________________________________________________________________
                            Gophered by Gophernicus/97 on NetBSD/amd64 8.0_BETA
Select a line number, or "help".
>

Example showing how to get and display the contents of a gopher uri:

CL-USER> (cl-gopher:display-contents
           (cl-gopher:get-line-contents
             (cl-gopher:parse-gopher-uri "sdf.org")))
    Welcome to the SDF Public Access UNIX System .. est. 1987

    Official Site of the Internet Gopher Club Underground Syndicate

    We offer FREE and inexpensive memberships for people interested
    in the UNIX system and internetworking.  Personal GOPHERSPACE
    is available to all users as well as hundreds of UNIX utilities,
    games and networking utilities.  We are a federally recognized
    non-profit 501(c)7 organization and we are supported entirely
    by donations and membership dues.  ssh://sdf.org

11     SUBMENU SDF PHLOGOSPHERE (226 phlogs)
12     SUBMENU SDF GOPHERSPACE (1119 ACTIVE users)
13     SUBMENU SDF GOPHERSPACE (1371 AGED users)
14     SUBMENU SDF GOPHERSPACE (373 ANCIENT users)
15     SUBMENU SDF Frequently Asked Questions (FAQ)
16     SUBMENU SDF Accredited University Courses
17     SUBMENU Software and Documentation for various computers
18     SEARCH-LINE GopherSpace SEARCH Engine
19     SUBMENU Floodgap's GOPHERSPACE
    ____________________________________________________________________________
                            Gophered by Gophernicus/97 on NetBSD/amd64 8.0_BETA

A very basic example of how a server could use the library. Assume remote-sock is a socket connected to a client:

CL-USER> (let ((lines (list
                       (make-instance 'cl-gopher:text-file
                                      :hostname "myserver.org"
                                      :port 70
                                      :selector "/Welcome.txt"
                                      :display-string "Welcome to myserver.org!")
                       (make-instance 'cl-gopher:submenu
                                      :hostname "myserver.org"
                                      :port 70
                                      :selector "/Documents"
                                      :display-string "View myserver.org's documents."))))
           (mapcar (lambda (gl) (cl-gopher:write-gopher-line gl :stream (usocket:socket-stream remote-sock))) lines)
           (write-line "." (usocket:socket-stream remote-sock))
           (force-output (usocket:socket-stream remote-sock)))

Output sent to remote:

0Welcome to myserver.org!   /Welcome.txt    myserver.org    70
1View myserver.org's documents. /Documents  myserver.org    70