summaryrefslogtreecommitdiff
path: root/gemini.cl
blob: 67399a96073aecf755c71e3c42f9f1226dfae72f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
(defun reverse-alist (alist)
  (loop for (a . b) in alist collect `(,b . ,a)))

(defvar +status-codes+
  '((10 . :input)
    (11 . :sensitive-input)
    (20 . :success)
    (30 . :redirect)
    (40 . :temporary-failure)
    (41 . :server-unavailable)
    (42 . :gci-error)
    (43 . :proxy-error)
    (44 . :slow-down)
    (50 . :permanent-failure)
    (51 . :not-found)
    (52 . :gone)
    (59 . :bad-request)
    (60 . :client-certificate-required)
    (61 . :certificate-not-authorised)
    (62 . :certificate-not-valid)))

(defun number->status (num)
  (cdr (assoc num +status-codes+)))

(defun status->number (key)
  (cdr (assoc key (reverse-alist +status-codes+))))

(defvar +site-root+ (pathname (user-homedir-pathname)))

(defun find-resource (url-path-string)
  ;; If the URL ends with a `.gmi` or `.gemini`, assume it points to a file and check if it exists.
  ;; Otherwise, assume it points to a directory, and check if `index.gmi` or `index.gemini` exists in that directory.
  ;; Returns the pathname of the file if it exists; nil otherwise.
  (let ((path-local (merge-pathnames (pathname url-path-string) +site-root+)))
    (cond (
      (search ".." url-path-string)
        ; TODO: Replace this with some sort of (is-unsafe-URL) function.
        ; URL is unsafe.
        nil)
      ((or (string= "gmi" (pathname-type path-local))
           (string= "gemini" (pathname-type path-local)))
        ; URL points to a file.
        (probe-file path-local))
      (t
        ; URL points to a directory.
        ; Due to how pathnames work, we must ensure that the last character in the URL is a single "/" for it to be treated as a directory.
        (let 
          ((path-local-dir (pathname
            (if (pathname-name path-local)
              (pathname (concatenate 'string (namestring path-local) "/"))
              path-local
          ))))
          (or (probe-file (merge-pathnames "index.gmi" path-local-dir))
              (probe-file (merge-pathnames "index.gemini" path-local-dir))))))))