From 80bc1e071bb03157b33a5877f032f9697e74fb13 Mon Sep 17 00:00:00 2001 From: Simon Brooke Date: Wed, 26 Feb 2020 13:58:01 +0000 Subject: [PATCH] Sort of works, well enough to know that the concept is valid. NOT NEARLY good enough to release! --- resources/config.edn | 2 +- resources/public/img/Unknown-pin.png | Bin 0 -> 1826 bytes resources/public/img/shadow_pin.png | Bin 0 -> 1966 bytes src/smeagol/finder.clj | 139 +++++++++++++++++++++++++++ src/smeagol/image_finder.clj | 44 --------- src/smeagol/routes/wiki.clj | 32 +++++- src/smeagol/util.clj | 6 ++ 7 files changed, 176 insertions(+), 47 deletions(-) create mode 100644 resources/public/img/Unknown-pin.png create mode 100644 resources/public/img/shadow_pin.png create mode 100644 src/smeagol/finder.clj delete mode 100644 src/smeagol/image_finder.clj diff --git a/resources/config.edn b/resources/config.edn index c6a66ae..a929a9d 100644 --- a/resources/config.edn +++ b/resources/config.edn @@ -45,7 +45,7 @@ :remote "https://cdnjs.cloudflare.com/ajax/libs/PapaParse/5.1.0/papaparse.min.js"}} :styles {:leaflet {:local "vendor/node_modules/leaflet/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" :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"}}} diff --git a/resources/public/img/Unknown-pin.png b/resources/public/img/Unknown-pin.png new file mode 100644 index 0000000000000000000000000000000000000000..f0b8fbb15f8d3ad76ce798d91491160e4edee0e0 GIT binary patch literal 1826 zcmV+-2i^FIP)00006VoOIv0RI60 z0RN!9r;`8x010qNS#tmY4c7nw4c7reD4Tcy000McNliru;R7B89S@JPi=6-f2Cqp( zK~z}7#aCTy6xS90&bc$QJL^9Tu`wV>X)7Z{?Kmw_(?n4p5~-*HW?O}-Rf|%Rhej1? z)k>8r^)cirNENiIQVH5biYz1=>@g&fAt(unFsNxF;-AK}xT-Nw)3wdo-nDmU?m2x} zLjv*d;-p8q(#&Y?Ip6uY-?@hXAP544VTd3I(g5~~$io1VSYF97^BDjK!Z7Sir_*R} zZwCcI000Ewn24m;tZBH>*tluf_x*TTt>-4a{{H^e!^79BjWI8WVYoX80?o}l`20=u)aN)wL7hinoK>(W=z%vaE4L4d^S~5%WMlbo*@|X1rPnNPzRngqs zJmR`;4B!xp$U~bpZMweHu-D*~bw2mj0p+EurRBasRegj3BvUEBxU}tzB=^?A@zuu% z)#U)FsHiNKG?gI=N7xiRcBYUJ0I2y61Lov;gqwf)@|EJ z>=6j?^lGh%a*ir%Il8!<&?UWrdNMA79ft9>(s`%8+z8wRKqWF<6aXT}VRc+4$0g+i zQf_aZ;${Ts6N>?`0!D$^BQ%o&Qco_XK!BxHks=|VP@)O~hyW$^-HSDFj3E%9AY!W? zU8&`K#ICvGI~YkA9dlVnU89+Vkuitts0Vf8VehwnglV1yfTGBa`6_9vUxC&}GA_Y5 zOzaR$X_0XmrSC-S5{Lj%s1OVllJ~Co<)e^D)y9h0irPqFV^LTIikhQGt`Z`erwA1j z{GIDLJT|fhzy6xRL<&R%A|htO%pzk5>=1|vY?UlQEeI^4VoMPtOCVAZladqv$2stR zOlu3Xkrv-sV1i0JBrlvFu|Mf1l9Hz&0x?QJ48a&C$0-3}L&RMAh4?0B5XEL(cMc5E zOIPT$vUXeXDXdl%u0_vvjp+|AFI3#l ze8Btc8lzdhg(tWv60QPinpPFTuvDikZ4(RTV&0)mnwbfC@Yss9AO@c6d1H zQU6NVSjZMd<5)E+>UjR4OA=E=Hd2UHh!xlZ`Sd}}G6En}@Y#FRni!?1ds~FdfL#&h{A-W0&w=9<07X%=vuvIv*L9H#ZoQ-8D|NNP0+c;6`=`md` z?0auKdUOC10b-RT&x{GPEC77`wZ=#$2^(o_>&6EQe|+2Ois<%>sAA0S{&&Xy;sR{W zKt!wU(Y13mphW{v7_F4o8(^(W$~P}xu?OE%xN|7Al*a=%uJQ|AB5bRoBVQmCdA{2* z060W6k0A^%Iy#yv@eI+M z{rwkLCla5&RwbmT;=j(b7bfXjnfbi=blFBU&CQc@87Ct2^z^PHqBaJwKa)CYXIyu{r&xen>TO1=cAAMccxOQ+=dP7Cz)BP zB)D@eX7ZV1sfh6D)2G+J`s!=VMD%B@}hhg}ubUJ-&IK4TZ zR|9w%z>fL6+_Ps-S95dIsOrb5>FMcNb@=d~9$X+wM*ut-hT+tX9XoLR`0|K9z5TP93)f*CnIH8tfC(OY*roR;G~0DO1m_0RZ!Ne~44?`Hr10AoNtQoCRd QBLDyZ07*qoM6N<$f+f;shX4Qo literal 0 HcmV?d00001 diff --git a/resources/public/img/shadow_pin.png b/resources/public/img/shadow_pin.png new file mode 100644 index 0000000000000000000000000000000000000000..07c4daa8da5879df63481756802790065671fadf GIT binary patch literal 1966 zcmV;f2T}NmP)Px#24YJ`L;(K){{a7>y{D4^000SaNLh0L00Gzl00Gzm`dp@R00007bV*G`2igZ8 z5Fi{_h}EqC00%BfL_t(o!@ZYFa^pr4hVxY*07_(2YRS{H^v3J<#^IGCwCrp2xpWOJ z`v}$z?4>-S)DoW{Q2CezKw149%W6+WFoM9MfDiwlnSbH;-+vGP;KH|W-@?0h?`Sj{ z(R3=(G*r}eT>`)u5y#9p2A~6Gst~CHfDs}lL}UQKh`>)aMU2lqEc)f{uI{?c*%oGY zBmWP;s;Wdp3bUfDYZ(*K1OTQf$&`o>iRgftYD6pna72Ux&_e=z3OQ^)fCfYWAVRoD zxVyP~s|qW3kcepiDM`V@KHLK$Qt=3o zh;XkEeony%fQT6WySs2oT^N4uA$=ojU*kbP=(Oh{oL; z`KRpJwrw#Qjp~%r1QCx?k`p36Nh!T#<`>L-z|18P6-3C0NQg*%9Rgyn-DlzUDiWc) zdmu)bg}O)M?n^U!9}(B?K97id`Idl}mzO-7%>)2SA|DeKQzCqsQgOn}ry_F9%r8V_ z%*-Q1OamYS3|RfYuSkgTs0Q6V)ZJS%+ojb2?5beV3BFN-4ccDV?SyGZ8ry;gXpOB4R{(u;*aW!KNSoV6Z0u0C>Nm zGqc7_mpSWuGy6}@`ASu<%xrFE_g&X*WY4A(@I zn27;^{`4gNk4Fu~2LTb`5us+@nb}rVS7vsrn&+x^t*UcXy+g!R+qTVgI_=~+fEO1R z{OZ*!QPt6CG#WGWbg<;9h@7M(FNyjF!%QU+3lTEFzOj6%?mlTSF^oYsb9J}Y%-5=U zVdgigIv?zLlXJcYfDIz-F@9O&2F(+d*?HRGRr>mK_ zX1X=g#h~0Ds(O`k{v#shs=6SewYzt#)ymG!&iwrR8~`AmY}cx)1OP@vG)^f^iRgHM zI%VdUDai|F*^h_xG<)vh9#Wc{xkh-aY8zEusOqhmUgxZHcfWD>J9l3*^KP+NXkFKK zc6Ju$=jRV?>dBC0Sys$^AVM={IuS`HB77>6jzwfD!ec}lG1HJ-5WWofQGkhudv4|) z;n~a^Gu`B@_wF{&S?8*H?e4cZ=SA0bTUFgPO{07De*N{=4>o=>BqAO%^D(oWipX~& za+*>)V&;j6RLoQ$q71|RBeM7;mVHRvhcoxk9?%+9Tbb#d*#qEQRo}b&(%l;o`NWRzPAtPf2Sjl9h={PE{&xNRv!$8c zndv-dotxP$0NknS8US|N?KXeTp3jCv#0etJ5a9?Br-)c1VgV4t(ddJZ8G~N#{?JU~ zkyisCygwd=Mnq?3t(k4yZK-N^W_qh?Hxcn(RhMnsZbYQLy1LRgZ{FDF?D=fSh$sLe z_4O7I5$f)F56Ijr)W@%I0I*)6u;F^JWe*P!IsmrrwsVh-nXXjr-rerZ{4PQls3*CI!GvL@eEH83Ai|Zw6aGKt_ZCKpyUQ?%qX2i-_HJ zyUmE0%d)hTk`Ln_}x~^+-&O0L7wQbvWUDr+~lg`ZY?d`1{9v<53 z*RTEJ;sP!&FaI{&b86Do>oug5sBPO05qCtiMg$$sdAo>M1HjtMnxcr^Zs%GQg{@Yr zsOvh`>-7gOKAX+rhaY|j0D$xJbNK!D-=C%2vmwvU&ivxy0?o`)N*w@fh8V^GmJxA> zh)vG9C8E4qskUwFKmGKRKi+4kF93jV4)yW+FRWs@=87f`p#T5?07*qoM6N<$f;>gG Aa{vGU literal 0 HcmV?d00001 diff --git a/src/smeagol/finder.clj b/src/smeagol/finder.clj new file mode 100644 index 0000000..9b4daa6 --- /dev/null +++ b/src/smeagol/finder.clj @@ -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}} diff --git a/src/smeagol/image_finder.clj b/src/smeagol/image_finder.clj deleted file mode 100644 index 81ef52e..0000000 --- a/src/smeagol/image_finder.clj +++ /dev/null @@ -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 ))) diff --git a/src/smeagol/routes/wiki.clj b/src/smeagol/routes/wiki.clj index 6695c36..2933fcb 100644 --- a/src/smeagol/routes/wiki.clj +++ b/src/smeagol/routes/wiki.clj @@ -18,6 +18,7 @@ [smeagol.authenticate :as auth] [smeagol.configuration :refer [config]] [smeagol.diff2html :as d2h] + [smeagol.finder :refer [find-image-url]] [smeagol.formatting :refer [md->html]] [smeagol.history :as hist] [smeagol.layout :as layout] @@ -31,7 +32,7 @@ [smeagol.configuration :refer [config]] [smeagol.include.resolve-local-file :as resolve] [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))) (POST "/edit-user" request (route/restricted (admin/edit-user 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))) (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)) (POST "/passwd" request (passwd-page request)) (GET "/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)) ) diff --git a/src/smeagol/util.clj b/src/smeagol/util.clj index 6989681..caf1396 100644 --- a/src/smeagol/util.clj +++ b/src/smeagol/util.clj @@ -61,6 +61,12 @@ (let [a (str (fs/absolute content-dir))] (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 "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