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
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
|
(ns mulk.benki.book_marx
(:refer-clojure)
(:use [clojure repl]
[hiccup core page-helpers]
[clojureql predicates]
[clojure.core.match :only [match]]
noir.core
[mulk.benki util db auth])
(:require [clojure.algo.monads :as m]
[clojure.java.jdbc :as sql]
[clojure.string :as string]
[clojureql.core :as cq]
[noir.request :as request]
[noir.session :as session])
(:import [org.jsoup.Jsoup]))
(def bookmark_tags (cq/table :bookmark_tags))
(def bookmarks (cq/table :bookmarks))
(def tags (cq/table :tags))
(def users (cq/table :users))
(def bookmarx-list-page {})
(def bookmarx-submission-page {})
(defn restrict-visibility [table user]
(if user
(cq/select table
(cq/where (or (=* :visibility "public")
(=* :visibility "protected")
(and (=* :visibility "private")
(=* :owner user)))))
(cq/select table
(cq/where (=* :visibility "public")))))
(defpage "/marx" {}
(let [user (session/get :user)
marks (-> bookmarks
(cq/join users (=* :bookmarks.owner :users.id))
(restrict-visibility (session/get :user))
(cq/sort [:date#desc]))]
(with-dbt
(layout bookmarx-list-page "Book Marx"
[:p
;;(.toString marks)
[:ul {:class "bookmarx-list"}
(for [mark @marks]
[:li {:class "bookmark"}
[:h2 {:class "bookmark-title"}
[:a {:href (:uri mark)}
(:title mark)]]
[:p {:class "bookmark-date"}
(:date mark)]
[:p {:class "bookmark-description"}
(:description mark)]])]]))))
(defmacro ignore-errors [& body]
`(try (do ~@body)
(catch java.lang.Exception e#
nil)))
(defpage [:get "/marx/submit"] {uri :uri, description :description, origin :origin}
(with-auth
(let [title (m/domonad m/maybe-m
;; FIXME: Using slurp here is a potential security problem
;; because it permits access to internal resources!
[:when uri
:when (or (.startsWith uri "http://")
(.startsWith uri "https://"))
soup (ignore-errors (slurp uri))
page (org.jsoup.Jsoup/parse soup)
title (.select page "title")]
(.text title))
origin (or origin (get-in (request/ring-request) [:headers "Referer"]))]
(layout bookmarx-submission-page "Submit New Bookmark"
[:form {:method "POST"}
[:table
[:tr [:td "URI: "] [:td [:input {:type "text", :name "uri", :size 100, :value uri}]]]
[:tr [:td "Title: "] [:td [:input {:type "text", :name "title", :size 100, :value title}]]]
[:tr [:td "Description: "] [:td [:textarea {:name "description", :rows 25, :cols 100}]]]
[:tr [:td "Tags: "] [:td [:input {:type "text", :name "tags", :size 100, :id "bookmark-tags-field"}]]]
[:tr
[:td "Visibility: "]
[:td
[:input {:type "radio", :name "visibility", :value "private"}
"Private"]
[:input {:type "radio", :name "visibility", :value "protected",
:checked "checked"}
"Semi-private"]
[:input {:type "radio", :name "visibility", :value "public"}
"Public"]]]]
[:input {:type "hidden", :name "origin", :value origin}]
[:input {:type "submit"}]]))))
(defpage [:post "/marx/submit"] {uri :uri, description :description,
title :title, tags :tags, visibility :visibility,
origin :origin}
(with-auth
(let [tagseq (map string/trim (string/split tags #","))
user (session/get :user)]
(with-dbt
(let [bookmark (sql/with-query-results
results
["INSERT INTO bookmarks (owner, uri, title, description,
visibility)
VALUES (?, ?, ?, ?, ?)
RETURNING id"
user uri title description visibility]
(:id (first (into () results))))]
(doseq [tag tagseq]
(sql/insert-values :bookmark_tags [:bookmark :tag] [bookmark tag]))))))
(if (and origin (not= origin ""))
(redirect origin)
(redirect (link :marx))))
;; (defpage "/users/:id/marx" {user :id}
;; (let [user (session/get :user)
;; marks (-> bookmarks
;; (cq/join users (cqp/=* :tags.owner user))
;; (sort [:date#desc]))]
;; (with-dbt
;; @marks)))
|