X-Git-Url: https://thelambdalab.xyz/gitweb/index.cgi?p=scratchy.git;a=blobdiff_plain;f=burrower.scm;h=fa8e1662c24cf0331bb91b614bf7b69995447f47;hp=581ea9c0d35db2d24c6cee48a90ea433ed8119d8;hb=d22cda7ea80777aa9ed10ec9b2917b9762fe5fe5;hpb=d359b34d425e0f30db847083007af17f7fc0ce13 diff --git a/burrower.scm b/burrower.scm index 581ea9c..fa8e166 100644 --- a/burrower.scm +++ b/burrower.scm @@ -18,7 +18,7 @@ ;;; Global constants -(define gopher-index-file-name "index") +(define gopher-index-filename "index") (define burrower-version "1.0.0") @@ -28,7 +28,6 @@ "This gopher hole was dug using Burrower v" burrower-version "\n" "Powered by Chicken Scheme!")) - ;;; Server loop ;; We don't yet use worker threads here to handle requests, @@ -55,7 +54,7 @@ (serve-selector (if (= (string-length selector) 0) "/" selector) - remote-ip config))) + config))) (print "... served selector '" selector "'. Closing connection.")) (o (exn) (print-error-message o out-port) @@ -69,12 +68,22 @@ ;;; Selector type inference -(define (has-suffix? selector . suffixes) - (if (null? suffixes) +(define (true-for-one? predicate values) + (if (null? values) #f - (if (string-suffix? (car suffixes) selector) + (if (predicate (car values)) #t - (apply has-suffix? selector (cdr suffixes))))) + (true-for-one? predicate (cdr values))))) + +(define (has-suffix? selector . suffixes) + (true-for-one? (lambda (suffix) + (string-suffix? suffix selector)) + suffixes)) + +(define (has-prefix? selector . prefixes) + (true-for-one? (lambda (prefix) + (string-prefix? prefix selector)) + prefixes)) (define (infer-selector-type selector) (let ((l (string-downcase selector))) @@ -82,28 +91,35 @@ ((or (= (string-length l) 0) (string-suffix? "/" l)) 1) ((has-suffix? l ".txt" ".org" ".md") 0) ((has-suffix? l ".png" ".jpg" ".gif" ".bmp" ".tif" ".tga") 'I) - ((has-suffix? l "?.scm") 7) + ((has-suffix? l "?.scm" "%3f.scm") 7) + ((has-prefix? l "url:" "/url:") 'h) (else 9)))) ;;; Selector retrieval -(define (serve-selector raw-selector remote-ip config) +(define (serve-selector raw-selector config) (let* ((selector-list (string-split raw-selector "\t")) (selector (car selector-list)) (arguments (cdr selector-list))) (case (infer-selector-type selector) ((1) (serve-directory selector config)) ((0) (serve-text-file selector config)) - ((7) (serve-query selector arguments remote-ip config)) + ((7) (serve-query selector arguments config)) + ((h) (serve-url selector config)) (else (serve-binary-file selector config))))) +(define (legal-filename? filename config) + (and (string-prefix? (config-root-dir config) + (normalize-pathname filename)) + (regular-file? filename))) + (define (serve-directory selector config) - (let ((file-name (make-pathname (list (config-root-dir config) selector) - gopher-index-file-name))) - (if (regular-file? file-name) + (let ((filename (make-pathname (list (config-root-dir config) selector) + gopher-index-filename))) + (if (legal-filename? filename config) (begin - (with-input-from-file file-name + (with-input-from-file filename (lambda () (let loop ((c (peek-char))) (if (eof-object? c) @@ -121,20 +137,20 @@ (error "Index file not found.")))) (define (serve-text-file selector config) - (let ((file-name (make-pathname (config-root-dir config) selector))) - (if (regular-file? file-name) - (with-input-from-file file-name + (let ((filename (make-pathname (config-root-dir config) selector))) + (if (legal-filename? filename config) + (with-input-from-file filename (lambda () (for-each (lambda (line) (print line "\r")) (read-lines)))) - (error "File not found." file-name)))) + (error "File not found." filename)))) (define (serve-binary-file selector config) - (let ((file-name (make-pathname (config-root-dir config) selector))) - (if (regular-file? file-name) - (with-input-from-file file-name + (let ((filename (make-pathname (config-root-dir config) selector))) + (if (legal-filename? filename config) + (with-input-from-file filename (lambda () (let loop ((b (read-byte))) (if (eof-object? b) @@ -142,23 +158,40 @@ (begin (write-byte b) (loop (read-byte))))))) - (error "File not found." file-name)))) + (error "File not found." filename)))) -(define (serve-query selector arguments remote-ip config) - (let ((file-name (make-pathname (config-root-dir config) selector))) - (if (and (regular-file? file-name) +(define (serve-query selector arguments config) + (let ((filename (make-pathname (config-root-dir config) + (string-translate* selector '(("%3f" . "?")))))) + (if (and (legal-filename? filename config) (= (length arguments) 1)) - (with-input-from-file file-name + (with-input-from-file filename (lambda () (serve-info-records (with-selector-dir selector config (lambda () - (apply (eval (read)) - (list (car arguments) remote-ip))))))) + (apply (eval (read)) arguments)))))) (error "Invalid query." selector arguments)))) +(define (serve-url selector config) + (let ((url (substring selector 4))) + (print + "Redirection" + "" + "" + "

If you are seeing this page, your gopher browser does not " + "properly support URL directory entries or cannot follow such " + "links.

" + "

If you are viewing this page using a web browser, you should " + "be redirected shortly. Otherwise, you can manually open the " + "the follwing url:\n" + "\n" + "" url "\n" + ""))) + + ;;; Index rendering (define (serve-info-records string) @@ -178,7 +211,9 @@ (('shell command) (serve-shell-command command dir-selector config)) (('eval expression) (serve-expression expression dir-selector config)) (('url display-string url) - (print #\h display-string "\tURL:" url "\tfake\t80\r")) + (print #\h display-string "\tURL:" url + "\t" (config-host config) + "\t" (config-port config) "\r")) ((type display-string selector host port) (print type display-string "\t" selector "\t" host "\t" port "\r")) ((type display-string selector host)