mirror of
https://github.com/journeyman-cc/smeagol.git
synced 2026-04-12 18:05:06 +00:00
Merge branch 'feature/17' into develop
This commit is contained in:
commit
19e5920c9d
7 changed files with 130 additions and 2 deletions
|
|
@ -65,6 +65,10 @@
|
||||||
:edit-users-title "Select user to edit"
|
:edit-users-title "Select user to edit"
|
||||||
;; title of edit users page
|
;; title of edit users page
|
||||||
:email-prompt "Email address" ;; text of the email widget prompt on edit user page
|
:email-prompt "Email address" ;; text of the email widget prompt on edit user page
|
||||||
|
:file-upload-link-text "You may link to this file using a link of the form"
|
||||||
|
;; Text introducing the link to an uploaded file
|
||||||
|
:file-upload-prompt "File to upload" ;; prompt string for the file upload widget
|
||||||
|
:file-upload-title "Upload a file" ;; title for the file upload page
|
||||||
:is-admin-prompt "Is administrator?"
|
:is-admin-prompt "Is administrator?"
|
||||||
:home-link "Home" ;; text of the home link on the menu
|
:home-link "Home" ;; text of the home link on the menu
|
||||||
:login-label "Log in!" ;; text of the login widget on the login page
|
:login-label "Log in!" ;; text of the login widget on the login page
|
||||||
|
|
|
||||||
BIN
resources/public/uploads/water.png
Normal file
BIN
resources/public/uploads/water.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 15 KiB |
|
|
@ -6,6 +6,7 @@
|
||||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
<link href="{{servlet-context}}/content/stylesheet.css" media="screen" rel="stylesheet" type="text/css" />
|
<link href="{{servlet-context}}/content/stylesheet.css" media="screen" rel="stylesheet" type="text/css" />
|
||||||
|
<link href="{{servlet-context}}/css/print.css" media="print" rel="stylesheet" type="text/css" />
|
||||||
{% block extra-headers %}
|
{% block extra-headers %}
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
</head>
|
</head>
|
||||||
|
|
@ -20,6 +21,7 @@
|
||||||
<li class="{{edit-users-selected}}"><a href="{{servlet-context}}/edit-users">{{config.edit-users-link}}</a></li>
|
<li class="{{edit-users-selected}}"><a href="{{servlet-context}}/edit-users">{{config.edit-users-link}}</a></li>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% if user %}
|
{% if user %}
|
||||||
|
<li class="{{upload-selected}}"><a href="upload">{{config.file-upload-title}}</a></li>
|
||||||
<li class="{{passwd-selected}}"><a href="passwd">{{config.change-pass-link}}</a></li>
|
<li class="{{passwd-selected}}"><a href="passwd">{{config.change-pass-link}}</a></li>
|
||||||
<li class="user" id="user">{{config.logged-in-as}} {{user}}</li>
|
<li class="user" id="user">{{config.logged-in-as}} {{user}}</li>
|
||||||
<li class="{{auth-selected}}"><a href="{{servlet-context}}/auth">
|
<li class="{{auth-selected}}"><a href="{{servlet-context}}/auth">
|
||||||
|
|
@ -90,4 +92,3 @@
|
||||||
<footer>
|
<footer>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
||||||
|
|
|
||||||
33
resources/templates/upload.html
Normal file
33
resources/templates/upload.html
Normal file
|
|
@ -0,0 +1,33 @@
|
||||||
|
{% extends "templates/base.html" %}
|
||||||
|
{% block content %}
|
||||||
|
<div id="content" class="auth">
|
||||||
|
{% if uploaded %}
|
||||||
|
{% if is-image %}
|
||||||
|
<img alt="Uploaded image" src="uploads/{{uploaded}}"/>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
{{config.file-upload-link-text}}:
|
||||||
|
|
||||||
|
<code></code>
|
||||||
|
</p>
|
||||||
|
{% else %}
|
||||||
|
<p>
|
||||||
|
{{config.file-upload-link-text}}:
|
||||||
|
|
||||||
|
<code>[Uploaded file](uploads/{{uploaded}})</code>
|
||||||
|
</p>
|
||||||
|
{% endif %}
|
||||||
|
{% else %}
|
||||||
|
<form action="{{servlet-context}}/upload" enctype="multipart/form-data" method="POST">
|
||||||
|
<p class="widget">
|
||||||
|
<label for="upload">{{config.file-upload-prompt}}</label>
|
||||||
|
<input name="upload" id="upload" type="file" required/>
|
||||||
|
</p>
|
||||||
|
<p class="widget">
|
||||||
|
<label for="submit">{{config.save-prompt}}</label>
|
||||||
|
<input name="submit" id="submit" type="submit" class="action" value="{{config.save-label}}"/>
|
||||||
|
</p>
|
||||||
|
</form>
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
{% endblock %}
|
||||||
|
|
@ -3,6 +3,7 @@
|
||||||
smeagol.routes.wiki
|
smeagol.routes.wiki
|
||||||
(:require [clojure.walk :refer :all]
|
(:require [clojure.walk :refer :all]
|
||||||
[clojure.java.io :as cjio]
|
[clojure.java.io :as cjio]
|
||||||
|
[clojure.string :as cs]
|
||||||
[cemerick.url :refer (url url-encode url-decode)]
|
[cemerick.url :refer (url url-encode url-decode)]
|
||||||
[compojure.core :refer :all]
|
[compojure.core :refer :all]
|
||||||
[clj-jgit.porcelain :as git]
|
[clj-jgit.porcelain :as git]
|
||||||
|
|
@ -17,6 +18,7 @@
|
||||||
[smeagol.formatting :refer [md->html]]
|
[smeagol.formatting :refer [md->html]]
|
||||||
[smeagol.layout :as layout]
|
[smeagol.layout :as layout]
|
||||||
[smeagol.util :as util]
|
[smeagol.util :as util]
|
||||||
|
[smeagol.uploads :as ul]
|
||||||
[smeagol.history :as hist]
|
[smeagol.history :as hist]
|
||||||
[smeagol.routes.admin :as admin]))
|
[smeagol.routes.admin :as admin]))
|
||||||
|
|
||||||
|
|
@ -145,6 +147,28 @@
|
||||||
:page page
|
:page page
|
||||||
:history (md->html (hist/find-history repo-path file-name))}))))
|
:history (md->html (hist/find-history repo-path file-name))}))))
|
||||||
|
|
||||||
|
(defn upload-page
|
||||||
|
"Render a form to allow the upload of a file."
|
||||||
|
[request]
|
||||||
|
(let [params (keywordize-keys (:params request))
|
||||||
|
data-path (str (io/resource-path) "/uploads/")
|
||||||
|
upload (:upload params)
|
||||||
|
uploaded (if upload (ul/store-upload params))]
|
||||||
|
(layout/render "upload.html"
|
||||||
|
(merge (util/standard-params request)
|
||||||
|
{:title (:file-upload-title layout/config)
|
||||||
|
:uploaded uploaded
|
||||||
|
:is-image (and
|
||||||
|
uploaded
|
||||||
|
(or
|
||||||
|
(cs/ends-with? uploaded ".gif")
|
||||||
|
(cs/ends-with? uploaded ".jpg")
|
||||||
|
(cs/ends-with? uploaded ".jpeg")
|
||||||
|
(cs/ends-with? uploaded ".png")
|
||||||
|
(cs/ends-with? uploaded ".GIF")
|
||||||
|
(cs/ends-with? uploaded ".JPG")
|
||||||
|
(cs/ends-with? uploaded ".PNG")))}))))
|
||||||
|
|
||||||
|
|
||||||
(defn version-page
|
(defn version-page
|
||||||
"Render a specific historical version of a page"
|
"Render a specific historical version of a page"
|
||||||
|
|
@ -246,4 +270,5 @@
|
||||||
(POST "/auth" request (auth-page request))
|
(POST "/auth" request (auth-page request))
|
||||||
(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)))
|
||||||
|
(POST "/upload" request (route/restricted (upload-page request))))
|
||||||
|
|
|
||||||
64
src/smeagol/uploads.clj
Normal file
64
src/smeagol/uploads.clj
Normal file
|
|
@ -0,0 +1,64 @@
|
||||||
|
(ns ^{:doc "Handle file uploads."
|
||||||
|
:author "Simon Brooke"}
|
||||||
|
smeagol.uploads
|
||||||
|
(:import [java.io File])
|
||||||
|
(:require [clojure.string :as cs]
|
||||||
|
[noir.io :as io]
|
||||||
|
[taoensso.timbre :as timbre]))
|
||||||
|
|
||||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
;;;;
|
||||||
|
;;;; 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
|
||||||
|
;;;;
|
||||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
|
||||||
|
(defn avoid-name-collisions
|
||||||
|
"Find a filename within this `path`, based on this `file-name`, that does not
|
||||||
|
reference an existing file. It is assumed that `path` ends with a path separator.
|
||||||
|
Returns a filename hwich does not currently reference a file within the path."
|
||||||
|
[path file-name]
|
||||||
|
(if (.exists (File. (str path file-name)))
|
||||||
|
(let [parts (cs/split file-name #"\.")
|
||||||
|
prefix (cs/join "." (butlast parts))
|
||||||
|
suffix (last parts)]
|
||||||
|
(first
|
||||||
|
(filter #(not (.exists (File. (str path %))))
|
||||||
|
(map #(str prefix "." % "." suffix) (range)))))
|
||||||
|
file-name))
|
||||||
|
|
||||||
|
|
||||||
|
(defn store-upload
|
||||||
|
"Store an upload both to the file system and to the database.
|
||||||
|
The issue with storing an upload is moving it into place.
|
||||||
|
If `params` are passed as a map, it is expected that this is a map from
|
||||||
|
an HTTP POST operation of a form with type `multipart/form-data`."
|
||||||
|
[params]
|
||||||
|
(let [upload (:upload params)
|
||||||
|
tmp-file (:tempfile upload)
|
||||||
|
path (str (io/resource-path) "uploads/")
|
||||||
|
filename (avoid-name-collisions path (:filename upload))]
|
||||||
|
(timbre/info
|
||||||
|
(str "Storing upload file: " upload))
|
||||||
|
(if tmp-file
|
||||||
|
(do
|
||||||
|
(.renameTo tmp-file
|
||||||
|
(File. (str path filename)))
|
||||||
|
filename)
|
||||||
|
(throw (Exception. "No file found?")))))
|
||||||
|
|
@ -2,6 +2,7 @@
|
||||||
:author "Simon Brooke"}
|
:author "Simon Brooke"}
|
||||||
smeagol.util
|
smeagol.util
|
||||||
(:require [noir.session :as session]
|
(:require [noir.session :as session]
|
||||||
|
[noir.io :as io]
|
||||||
[smeagol.authenticate :as auth]
|
[smeagol.authenticate :as auth]
|
||||||
[smeagol.formatting :refer [md->html]]))
|
[smeagol.formatting :refer [md->html]]))
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue