mirror of
https://github.com/journeyman-cc/smeagol.git
synced 2026-04-12 18:05:06 +00:00
Sort of works, well enough to know that the concept is valid.
NOT NEARLY good enough to release!
This commit is contained in:
parent
5a784f4497
commit
80bc1e071b
7 changed files with 176 additions and 47 deletions
|
|
@ -45,7 +45,7 @@
|
||||||
:remote "https://cdnjs.cloudflare.com/ajax/libs/PapaParse/5.1.0/papaparse.min.js"}}
|
:remote "https://cdnjs.cloudflare.com/ajax/libs/PapaParse/5.1.0/papaparse.min.js"}}
|
||||||
:styles {:leaflet {:local "vendor/node_modules/leaflet/dist/leaflet.css"
|
:styles {:leaflet {:local "vendor/node_modules/leaflet/dist/leaflet.css"
|
||||||
:remote "https://unpkg.com/leaflet@1.6.0/dist/leaflet.css"}}
|
:remote "https://unpkg.com/leaflet@1.6.0/dist/leaflet.css"}}
|
||||||
:icon-url-base "uploads/map-pin/"}
|
:icon-url-base "map-pin/"}
|
||||||
:mermaid {:formatter "smeagol.extensions.mermaid/process-mermaid"
|
:mermaid {:formatter "smeagol.extensions.mermaid/process-mermaid"
|
||||||
:scripts {:core {:local "vendor/node_modules/mermaid/dist/mermaid.min.js"
|
:scripts {:core {:local "vendor/node_modules/mermaid/dist/mermaid.min.js"
|
||||||
:remote "https://cdnjs.cloudflare.com/ajax/libs/mermaid/8.4.6/mermaid.min.js"}}}
|
:remote "https://cdnjs.cloudflare.com/ajax/libs/mermaid/8.4.6/mermaid.min.js"}}}
|
||||||
|
|
|
||||||
BIN
resources/public/img/Unknown-pin.png
Normal file
BIN
resources/public/img/Unknown-pin.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.8 KiB |
BIN
resources/public/img/shadow_pin.png
Normal file
BIN
resources/public/img/shadow_pin.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.9 KiB |
139
src/smeagol/finder.clj
Normal file
139
src/smeagol/finder.clj
Normal file
|
|
@ -0,0 +1,139 @@
|
||||||
|
(ns ^{:doc "Find (by doing a 302 redirect to) appropriate files; if no
|
||||||
|
appropriate file is found return a 302 redirect to a default file."
|
||||||
|
:author "Simon Brooke"}
|
||||||
|
smeagol.finder
|
||||||
|
(:require [clojure.string :as cs]
|
||||||
|
[me.raynes.fs :as fs]
|
||||||
|
[noir.io :as io]
|
||||||
|
[noir.response :as response]
|
||||||
|
[smeagol.configuration :refer [config]]
|
||||||
|
[smeagol.util :refer [local-url-base content-dir]]
|
||||||
|
[taoensso.timbre :as log]))
|
||||||
|
|
||||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
;;;;
|
||||||
|
;;;; Smeagol: a very simple Wiki engine.
|
||||||
|
;;;;
|
||||||
|
;;;; This program is free software; you can redistribute it and/or
|
||||||
|
;;;; modify it under the terms of the GNU General Public License
|
||||||
|
;;;; as published by the Free Software Foundation; either version 2
|
||||||
|
;;;; of the License, or (at your option) any later version.
|
||||||
|
;;;;
|
||||||
|
;;;; This program is distributed in the hope that it will be useful,
|
||||||
|
;;;; but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
;;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
;;;; GNU General Public License for more details.
|
||||||
|
;;;;
|
||||||
|
;;;; You should have received a copy of the GNU General Public License
|
||||||
|
;;;; along with this program; if not, write to the Free Software
|
||||||
|
;;;; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
|
||||||
|
;;;; USA.
|
||||||
|
;;;;
|
||||||
|
;;;; Copyright (C) 2017 Simon Brooke
|
||||||
|
;;;;
|
||||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
|
||||||
|
;; See:
|
||||||
|
;; https://github.com/weavejester/compojure/wiki/Routes-In-Detail
|
||||||
|
;; https://github.com/weavejester/compojure/wiki/Destructuring-Syntax
|
||||||
|
|
||||||
|
(defn to-url
|
||||||
|
"Given the absolute file path `fqn`, return the relative URL to that path
|
||||||
|
within Smeagol, if any, else `nil`."
|
||||||
|
[fqn]
|
||||||
|
(let [f (when fqn (str fqn))
|
||||||
|
l (str local-url-base)
|
||||||
|
c (str content-dir)]
|
||||||
|
(cond
|
||||||
|
(nil? f) nil
|
||||||
|
(cs/starts-with? f l) (subs f (count l))
|
||||||
|
;; content-dir may not be within local-url-base
|
||||||
|
;; TODO: potential bad bug: check that when uploads isn't within local-url-base
|
||||||
|
;; the right copies of files are actually getting served!
|
||||||
|
(cs/starts-with? f c) (str "content/" (subs f (count c))))))
|
||||||
|
|
||||||
|
|
||||||
|
(defn find-file-on-path
|
||||||
|
"Find a file with a name like this `n` on this `path` with
|
||||||
|
one of these `extensions`. Question: should we recurse down
|
||||||
|
the hierarchy?"
|
||||||
|
[n path extensions]
|
||||||
|
(let [ext (fs/extension n)
|
||||||
|
basename (subs n 0 (- (count n) (count ext)))
|
||||||
|
fqn (fs/absolute (fs/file path n))]
|
||||||
|
(if (and (fs/exists? fqn) (fs/readable? fqn))
|
||||||
|
fqn
|
||||||
|
(first
|
||||||
|
(remove
|
||||||
|
nil?
|
||||||
|
(map
|
||||||
|
#(let [fqn' (fs/absolute (fs/file path (str basename %)))]
|
||||||
|
(when (and (fs/exists? fqn') (fs/readable? fqn'))
|
||||||
|
fqn'))
|
||||||
|
extensions))))))
|
||||||
|
|
||||||
|
|
||||||
|
(defn find-file-on-paths
|
||||||
|
"Find a file with a name like this `n` on one of these `paths` with
|
||||||
|
one of these `extensions`"
|
||||||
|
[n paths extensions]
|
||||||
|
(first
|
||||||
|
(remove
|
||||||
|
nil?
|
||||||
|
(map
|
||||||
|
#(find-file-on-path n % extensions)
|
||||||
|
paths))))
|
||||||
|
|
||||||
|
|
||||||
|
(defn find-image-url
|
||||||
|
"Return a 302 redirect to
|
||||||
|
1. The requested file, if available;
|
||||||
|
2. This default URL otherwise."
|
||||||
|
[request requested-name default-url paths]
|
||||||
|
(let [url (to-url
|
||||||
|
(find-file-on-paths requested-name paths
|
||||||
|
[".gif" ".png" ".jpg" ".jpeg" ".svg"]))]
|
||||||
|
(if url
|
||||||
|
(log/info "Found image" requested-name "at" url)
|
||||||
|
(log/warn "Failed to find image matching" requested-name))
|
||||||
|
(response/redirect
|
||||||
|
;; (str "/" (:servlet-context request) url) ;; TODO: >>> Nasty
|
||||||
|
(if url
|
||||||
|
(str (name (:scheme request)) "://" (:host request) ":" (:server-port request) "/" url)
|
||||||
|
default-url)
|
||||||
|
:found )))
|
||||||
|
|
||||||
|
|
||||||
|
;; (def r {:ssl-client-cert nil,
|
||||||
|
;; :access-rules [{:redirect "/auth",
|
||||||
|
;; :rule #object[smeagol.handler$user_access 0x7ee9346 "smeagol.handler$user_access@7ee9346"]}],
|
||||||
|
;; :protocol "HTTP/1.1",
|
||||||
|
;; :cookies {"ring-session" {:value "4e7c059e-2796-44a0-b03a-c712dae43588"}},
|
||||||
|
;; :remote-addr "127.0.0.1",
|
||||||
|
;; :params {:n "froboz"},
|
||||||
|
;; :flash nil,
|
||||||
|
;; :route-params {:n "froboz"},
|
||||||
|
;; :headers {"cookie" "ring-session=4e7c059e-2796-44a0-b03a-c712dae43588",
|
||||||
|
;; "accept" "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8",
|
||||||
|
;; "upgrade-insecure-requests" "1", "user-agent" "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:73.0) Gecko/20100101 Firefox/73.0",
|
||||||
|
;; "connection" "keep-alive",
|
||||||
|
;; "host" "localhost:3000",
|
||||||
|
;; "accept-language" "en-GB,en;q=0.7,en-US;q=0.3",
|
||||||
|
;; "accept-encoding" "gzip, deflate",
|
||||||
|
;; "dnt" "1"},
|
||||||
|
;; :server-port 3000,
|
||||||
|
;; :content-length nil,
|
||||||
|
;; :form-params {},
|
||||||
|
;; :session/key "4e7c059e-2796-44a0-b03a-c712dae43588",
|
||||||
|
;; :query-params {},
|
||||||
|
;; :content-type nil,
|
||||||
|
;; :character-encoding nil,
|
||||||
|
;; :uri "/map-pin/froboz",
|
||||||
|
;; :server-name "localhost",
|
||||||
|
;; :query-string nil,
|
||||||
|
;; :body #object[org.eclipse.jetty.server.HttpInputOverHTTP 0x5abc1216 "HttpInputOverHTTP@5abc1216"],
|
||||||
|
;; :multipart-params {},
|
||||||
|
;; :scheme :http,
|
||||||
|
;; :request-method :get,
|
||||||
|
;; :session {:ring.middleware.anti-forgery/anti-forgery-token "2HVXUnBfpuw6kpLTWXTbiSk4zQN5/qPfvJtI/rw5Ju+m/f5I4r5nsOeEr1tuS5YWrXlNRWO6ruX/MHl4",
|
||||||
|
;; :ring.middleware.session-timeout/idle-timeout 1582725564}}
|
||||||
|
|
@ -1,44 +0,0 @@
|
||||||
(ns ^{:doc "Find (by doing a 302 redirect to) appropriate images; if no
|
|
||||||
appropriate image is found return a 302 redirect to a default image."
|
|
||||||
:author "Simon Brooke"}
|
|
||||||
smeagol.uploads
|
|
||||||
(:require [clojure.string :as cs]
|
|
||||||
[me.raynes.fs :as fs]
|
|
||||||
[noir.io :as nio]
|
|
||||||
[noir.response :as response]
|
|
||||||
))
|
|
||||||
|
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
||||||
;;;;
|
|
||||||
;;;; Smeagol: a very simple Wiki engine.
|
|
||||||
;;;;
|
|
||||||
;;;; This program is free software; you can redistribute it and/or
|
|
||||||
;;;; modify it under the terms of the GNU General Public License
|
|
||||||
;;;; as published by the Free Software Foundation; either version 2
|
|
||||||
;;;; of the License, or (at your option) any later version.
|
|
||||||
;;;;
|
|
||||||
;;;; This program is distributed in the hope that it will be useful,
|
|
||||||
;;;; but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
;;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
;;;; GNU General Public License for more details.
|
|
||||||
;;;;
|
|
||||||
;;;; You should have received a copy of the GNU General Public License
|
|
||||||
;;;; along with this program; if not, write to the Free Software
|
|
||||||
;;;; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
|
|
||||||
;;;; USA.
|
|
||||||
;;;;
|
|
||||||
;;;; Copyright (C) 2017 Simon Brooke
|
|
||||||
;;;;
|
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
||||||
|
|
||||||
;; See:
|
|
||||||
;; https://github.com/weavejester/compojure/wiki/Routes-In-Detail
|
|
||||||
;; https://github.com/weavejester/compojure/wiki/Destructuring-Syntax
|
|
||||||
|
|
||||||
(defn find-image
|
|
||||||
"Return a 302 redirect to
|
|
||||||
1. The requested file, if available;
|
|
||||||
2. This default URL otherwise."
|
|
||||||
[request requested-name default-url paths-to-explore]
|
|
||||||
(let [url (do-something-to-find-appropriate-file request)]
|
|
||||||
(response/redirect url :found )))
|
|
||||||
|
|
@ -18,6 +18,7 @@
|
||||||
[smeagol.authenticate :as auth]
|
[smeagol.authenticate :as auth]
|
||||||
[smeagol.configuration :refer [config]]
|
[smeagol.configuration :refer [config]]
|
||||||
[smeagol.diff2html :as d2h]
|
[smeagol.diff2html :as d2h]
|
||||||
|
[smeagol.finder :refer [find-image-url]]
|
||||||
[smeagol.formatting :refer [md->html]]
|
[smeagol.formatting :refer [md->html]]
|
||||||
[smeagol.history :as hist]
|
[smeagol.history :as hist]
|
||||||
[smeagol.layout :as layout]
|
[smeagol.layout :as layout]
|
||||||
|
|
@ -31,7 +32,7 @@
|
||||||
[smeagol.configuration :refer [config]]
|
[smeagol.configuration :refer [config]]
|
||||||
[smeagol.include.resolve-local-file :as resolve]
|
[smeagol.include.resolve-local-file :as resolve]
|
||||||
[smeagol.include :as include]
|
[smeagol.include :as include]
|
||||||
[smeagol.util :refer [content-dir local-url]]))
|
[smeagol.util :refer [content-dir local-url local-url-base upload-dir]]))
|
||||||
|
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
;;;;
|
;;;;
|
||||||
|
|
@ -466,12 +467,39 @@
|
||||||
(GET "/edit-user" request (route/restricted (admin/edit-user request)))
|
(GET "/edit-user" request (route/restricted (admin/edit-user request)))
|
||||||
(POST "/edit-user" request (route/restricted (admin/edit-user request)))
|
(POST "/edit-user" request (route/restricted (admin/edit-user request)))
|
||||||
(GET "/history" request (history-page request))
|
(GET "/history" request (history-page request))
|
||||||
|
(GET "/image/:n" request (find-image-url
|
||||||
|
request
|
||||||
|
(-> request :route-params :n)
|
||||||
|
"http://localhost:3000/img/smeagol.png"
|
||||||
|
[(fs/file local-url-base "img")
|
||||||
|
upload-dir
|
||||||
|
;; TODO: should map over the configured
|
||||||
|
;; thumbnail paths in descending order
|
||||||
|
;; by size - generally, bigger images are
|
||||||
|
;; better.
|
||||||
|
(fs/file upload-dir "med")
|
||||||
|
(fs/file upload-dir "small")
|
||||||
|
(fs/file upload-dir "map-pin")]))
|
||||||
(GET "/list-uploads" request (route/restricted (list-uploads-page request)))
|
(GET "/list-uploads" request (route/restricted (list-uploads-page request)))
|
||||||
(POST "/list-uploads" request (route/restricted (list-uploads-page request)))
|
(POST "/list-uploads" request (route/restricted (list-uploads-page request)))
|
||||||
(GET "/version" request (version-page request))
|
(GET "/map-pin/:n" request (find-image-url
|
||||||
|
request
|
||||||
|
(-> request :route-params :n)
|
||||||
|
"http://localhost:3000/img/Unknown-pin.png"
|
||||||
|
[(fs/file local-url-base "img")
|
||||||
|
;; TODO: should map over the configured
|
||||||
|
;; thumbnail paths in ascending order
|
||||||
|
;; by size - for map pins, smaller images are
|
||||||
|
;; better.
|
||||||
|
(fs/file upload-dir "map-pin")
|
||||||
|
(fs/file upload-dir "small")
|
||||||
|
(fs/file upload-dir "med")
|
||||||
|
upload-dir
|
||||||
|
local-url-base]))
|
||||||
(GET "/passwd" request (passwd-page request))
|
(GET "/passwd" request (passwd-page request))
|
||||||
(POST "/passwd" request (passwd-page request))
|
(POST "/passwd" request (passwd-page request))
|
||||||
(GET "/upload" request (route/restricted (upload-page request)))
|
(GET "/upload" request (route/restricted (upload-page request)))
|
||||||
(POST "/upload" request (route/restricted (upload-page request)))
|
(POST "/upload" request (route/restricted (upload-page request)))
|
||||||
|
(GET "/version" request (version-page request))
|
||||||
(GET "/wiki" request (wiki-page request))
|
(GET "/wiki" request (wiki-page request))
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -61,6 +61,12 @@
|
||||||
(let [a (str (fs/absolute content-dir))]
|
(let [a (str (fs/absolute content-dir))]
|
||||||
(subs a 0 (- (count a) (count "content")))))
|
(subs a 0 (- (count a) (count "content")))))
|
||||||
|
|
||||||
|
;; (def local-url-base
|
||||||
|
;; "Essentially, the slash-terminated absolute path of the `public` resource
|
||||||
|
;; directory. **NOTE** that this MAY NOT contain `content-dir`."
|
||||||
|
;; (cjio/file (io/resource-path)))
|
||||||
|
|
||||||
|
|
||||||
(defn not-servable-reason
|
(defn not-servable-reason
|
||||||
"As a string, the reason this `file-path` cannot safely be served, or `nil`
|
"As a string, the reason this `file-path` cannot safely be served, or `nil`
|
||||||
if it is safe to serve. This reason may be logged, but should *not* be
|
if it is safe to serve. This reason may be logged, but should *not* be
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue