From f837ea951a3b8cd8915b1757311cd0de0c2afb08 Mon Sep 17 00:00:00 2001 From: Christian Mueller Date: Fri, 3 Jan 2014 14:44:40 +0100 Subject: [PATCH] cssgen & clojurescript dependencies deletes --- project.clj | 12 --- resources/public/js/main.js | 44 ++++++++ resources/public/js/md5.js | 184 ++++++++++++++++++++++++++++++++++ resources/public/style.css | 154 ++++++++++++++++++++++++++++ src-cljs/main.cljs | 94 ----------------- src/NoteHub/crossover/lib.clj | 19 ---- src/NoteHub/storage.clj | 5 +- src/NoteHub/views/common.clj | 7 +- src/NoteHub/views/css.clj | 179 --------------------------------- src/NoteHub/views/pages.clj | 21 +++- 10 files changed, 406 insertions(+), 313 deletions(-) create mode 100644 resources/public/js/main.js create mode 100644 resources/public/js/md5.js create mode 100644 resources/public/style.css delete mode 100644 src-cljs/main.cljs delete mode 100644 src/NoteHub/crossover/lib.clj delete mode 100644 src/NoteHub/views/css.clj diff --git a/project.clj b/project.clj index 48090e3..5541cb4 100644 --- a/project.clj +++ b/project.clj @@ -3,21 +3,9 @@ :dependencies [[org.clojure/clojure "1.3.0"] [hiccup "1.0.0"] [ring/ring-core "1.1.0"] - [cssgen "0.2.6"] [clj-redis "0.0.12"] [org.pegdown/pegdown "1.1.0"] [noir "1.3.0-beta1"]] - :plugins [[lein-cljsbuild "0.1.10"]] - :hooks [leiningen.cljsbuild] :jvm-opts ["-Dfile.encoding=utf-8"] - :cljsbuild - {:crossovers [NoteHub.crossover], - :builds - [{:source-path "src-cljs", - :compiler - {:output-dir "resources/public/cljs/", - :output-to "resources/public/cljs/main.js", - :optimizations :whitespace, - :pretty-print true}}]} :main NoteHub.server) diff --git a/resources/public/js/main.js b/resources/public/js/main.js new file mode 100644 index 0000000..ded358a --- /dev/null +++ b/resources/public/js/main.js @@ -0,0 +1,44 @@ +var hash = function (input) { + var shortMod = function(i) { return i % 32767 }; + var charCodes = input.split("") + .filter(function(c){ return c != "\n" && c != "\r" }) + .map(function(c){ return c.charCodeAt(0) }); + var h = 0; + for(var i in charCodes) + h = shortMod(h + shortMod(charCodes[i] * (h % 2 != 0 ? 16381 ^ i : 16381 & i))); + return h; +} + +var mdConverter = new Markdown.Converter(); +var $ = function(id){ return document.getElementById(id); } +var $draft = $("draft"); +var $action = $("action"); +var $preview = $("preview"); +var $password = $("password"); +var $plain_password = $("plain-password"); +var $input_elems = $("input-elems"); +var $dashed_line = $("dashed-line"); +var iosDetected = navigator.userAgent.match("(iPad|iPod|iPhone)"); +var timer = null; +var timerDelay = iosDetected ? 800 : 400; +var show = function(elem) { elem.style.display = "block" } + +var updatePreview = function(){ + clearTimeout(timer); + var content = $draft.value; + var delay = Math.min(timerDelay, timerDelay * (content.length / 400)); + timer = setTimeout(function(){ + show($dashed_line); + show($input_elems); + $preview.innerHTML = mdConverter.makeHtml(content); + }, delay); +}; + +if($action.value == "update") updatePreview(); else $draft.value = ""; +if(iosDetected) $draft.className += " ui-border"; else $draft.focus(); +$draft.onkeyup = updatePreview; +$("publish-button").onclick = function(e) { + if($plain_password.value != "") $password.value = md5($plain_password.value); + $plain_password.value = null; + $("session-value").value = hash($draft.value + $("session-key").value); +} diff --git a/resources/public/js/md5.js b/resources/public/js/md5.js new file mode 100644 index 0000000..6876bc3 --- /dev/null +++ b/resources/public/js/md5.js @@ -0,0 +1,184 @@ +function md5cycle(x, k) { +var a = x[0], b = x[1], c = x[2], d = x[3]; + +a = ff(a, b, c, d, k[0], 7, -680876936); +d = ff(d, a, b, c, k[1], 12, -389564586); +c = ff(c, d, a, b, k[2], 17, 606105819); +b = ff(b, c, d, a, k[3], 22, -1044525330); +a = ff(a, b, c, d, k[4], 7, -176418897); +d = ff(d, a, b, c, k[5], 12, 1200080426); +c = ff(c, d, a, b, k[6], 17, -1473231341); +b = ff(b, c, d, a, k[7], 22, -45705983); +a = ff(a, b, c, d, k[8], 7, 1770035416); +d = ff(d, a, b, c, k[9], 12, -1958414417); +c = ff(c, d, a, b, k[10], 17, -42063); +b = ff(b, c, d, a, k[11], 22, -1990404162); +a = ff(a, b, c, d, k[12], 7, 1804603682); +d = ff(d, a, b, c, k[13], 12, -40341101); +c = ff(c, d, a, b, k[14], 17, -1502002290); +b = ff(b, c, d, a, k[15], 22, 1236535329); + +a = gg(a, b, c, d, k[1], 5, -165796510); +d = gg(d, a, b, c, k[6], 9, -1069501632); +c = gg(c, d, a, b, k[11], 14, 643717713); +b = gg(b, c, d, a, k[0], 20, -373897302); +a = gg(a, b, c, d, k[5], 5, -701558691); +d = gg(d, a, b, c, k[10], 9, 38016083); +c = gg(c, d, a, b, k[15], 14, -660478335); +b = gg(b, c, d, a, k[4], 20, -405537848); +a = gg(a, b, c, d, k[9], 5, 568446438); +d = gg(d, a, b, c, k[14], 9, -1019803690); +c = gg(c, d, a, b, k[3], 14, -187363961); +b = gg(b, c, d, a, k[8], 20, 1163531501); +a = gg(a, b, c, d, k[13], 5, -1444681467); +d = gg(d, a, b, c, k[2], 9, -51403784); +c = gg(c, d, a, b, k[7], 14, 1735328473); +b = gg(b, c, d, a, k[12], 20, -1926607734); + +a = hh(a, b, c, d, k[5], 4, -378558); +d = hh(d, a, b, c, k[8], 11, -2022574463); +c = hh(c, d, a, b, k[11], 16, 1839030562); +b = hh(b, c, d, a, k[14], 23, -35309556); +a = hh(a, b, c, d, k[1], 4, -1530992060); +d = hh(d, a, b, c, k[4], 11, 1272893353); +c = hh(c, d, a, b, k[7], 16, -155497632); +b = hh(b, c, d, a, k[10], 23, -1094730640); +a = hh(a, b, c, d, k[13], 4, 681279174); +d = hh(d, a, b, c, k[0], 11, -358537222); +c = hh(c, d, a, b, k[3], 16, -722521979); +b = hh(b, c, d, a, k[6], 23, 76029189); +a = hh(a, b, c, d, k[9], 4, -640364487); +d = hh(d, a, b, c, k[12], 11, -421815835); +c = hh(c, d, a, b, k[15], 16, 530742520); +b = hh(b, c, d, a, k[2], 23, -995338651); + +a = ii(a, b, c, d, k[0], 6, -198630844); +d = ii(d, a, b, c, k[7], 10, 1126891415); +c = ii(c, d, a, b, k[14], 15, -1416354905); +b = ii(b, c, d, a, k[5], 21, -57434055); +a = ii(a, b, c, d, k[12], 6, 1700485571); +d = ii(d, a, b, c, k[3], 10, -1894986606); +c = ii(c, d, a, b, k[10], 15, -1051523); +b = ii(b, c, d, a, k[1], 21, -2054922799); +a = ii(a, b, c, d, k[8], 6, 1873313359); +d = ii(d, a, b, c, k[15], 10, -30611744); +c = ii(c, d, a, b, k[6], 15, -1560198380); +b = ii(b, c, d, a, k[13], 21, 1309151649); +a = ii(a, b, c, d, k[4], 6, -145523070); +d = ii(d, a, b, c, k[11], 10, -1120210379); +c = ii(c, d, a, b, k[2], 15, 718787259); +b = ii(b, c, d, a, k[9], 21, -343485551); + +x[0] = add32(a, x[0]); +x[1] = add32(b, x[1]); +x[2] = add32(c, x[2]); +x[3] = add32(d, x[3]); + +} + +function cmn(q, a, b, x, s, t) { +a = add32(add32(a, q), add32(x, t)); +return add32((a << s) | (a >>> (32 - s)), b); +} + +function ff(a, b, c, d, x, s, t) { +return cmn((b & c) | ((~b) & d), a, b, x, s, t); +} + +function gg(a, b, c, d, x, s, t) { +return cmn((b & d) | (c & (~d)), a, b, x, s, t); +} + +function hh(a, b, c, d, x, s, t) { +return cmn(b ^ c ^ d, a, b, x, s, t); +} + +function ii(a, b, c, d, x, s, t) { +return cmn(c ^ (b | (~d)), a, b, x, s, t); +} + +function md51(s) { +txt = ''; +var n = s.length, +state = [1732584193, -271733879, -1732584194, 271733878], i; +for (i=64; i<=s.length; i+=64) { +md5cycle(state, md5blk(s.substring(i-64, i))); +} +s = s.substring(i-64); +var tail = [0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0]; +for (i=0; i>2] |= s.charCodeAt(i) << ((i%4) << 3); +tail[i>>2] |= 0x80 << ((i%4) << 3); +if (i > 55) { +md5cycle(state, tail); +for (i=0; i<16; i++) tail[i] = 0; +} +tail[14] = n*8; +md5cycle(state, tail); +return state; +} + +/* there needs to be support for Unicode here, + * unless we pretend that we can redefine the MD-5 + * algorithm for multi-byte characters (perhaps + * by adding every four 16-bit characters and + * shortening the sum to 32 bits). Otherwise + * I suggest performing MD-5 as if every character + * was two bytes--e.g., 0040 0025 = @%--but then + * how will an ordinary MD-5 sum be matched? + * There is no way to standardize text to something + * like UTF-8 before transformation; speed cost is + * utterly prohibitive. The JavaScript standard + * itself needs to look at this: it should start + * providing access to strings as preformed UTF-8 + * 8-bit unsigned value arrays. + */ +function md5blk(s) { /* I figured global was faster. */ +var md5blks = [], i; /* Andy King said do it this way. */ +for (i=0; i<64; i+=4) { +md5blks[i>>2] = s.charCodeAt(i) ++ (s.charCodeAt(i+1) << 8) ++ (s.charCodeAt(i+2) << 16) ++ (s.charCodeAt(i+3) << 24); +} +return md5blks; +} + +var hex_chr = '0123456789abcdef'.split(''); + +function rhex(n) +{ +var s='', j=0; +for(; j<4; j++) +s += hex_chr[(n >> (j * 8 + 4)) & 0x0F] ++ hex_chr[(n >> (j * 8)) & 0x0F]; +return s; +} + +function hex(x) { +for (var i=0; i> 16) + (y >> 16) + (lsw >> 16); +return (msw << 16) | (lsw & 0xFFFF); +} +} diff --git a/resources/public/style.css b/resources/public/style.css new file mode 100644 index 0000000..c05ff9c --- /dev/null +++ b/resources/public/style.css @@ -0,0 +1,154 @@ +a { + color: #097; + text-decoration: none; + border-bottom: 1px dotted; +} +a:hover { + color: #0a8; +} + +a:visited { + color: #054; +} +#draft { + margin-bottom: 3em; +} +.ui-border { + border-radius: 3px; + border: 1px solid #333; +} +.button { + cursor: pointer; +} +.ui-elem { + font-weight: 300; + font-family: 'Helvetica Neue','Helvetica','Arial','Lucida Grande','sans-serif'; + border-radius: 3px; + border: 1px solid #333; + padding: 0.3em; + opacity: 0.8; + font-size: 1em; + background: #fff; +} +.landing-button, table, tr, td, textarea, fieldset { + border: none; +} +.landing-button { + box-shadow: 0 2px 5px #aaa; + text-decoration: none; + font-size: 1.5em; + background: #0a2; + border-radius: 10px; + padding: 10px; + font-weight: 300; + font-family: 'Helvetica Neue','Helvetica','Arial','Lucida Grande','sans-serif'; +} +.landing-button:hover { + background: #0b2; +} +#panel { + font-weight: 300; + font-family: 'Helvetica Neue','Helvetica','Arial','Lucida Grande','sans-serif'; + position: fixed; + width: 100%; + border-top: 1px dotted #888; + background: #efefef; + padding: 0.2em; + bottom: 0px; + font-size: 0.7em; + text-align: center; +} +#panel a { + border: none; +} +html, body { + background: #fff; + color: #333; + margin: 0; + padding: 0; +} +#stats { + +} +#stats tr { + +} +#stats tr > td:first-child { + text-align: right; +} +.helvetica-neue { + font-weight: 300; + font-family: 'Helvetica Neue','Helvetica','Arial','Lucida Grande','sans-serif'; +} +#hero { + padding-top: 5em; + padding-bottom: 5em; + text-align: center; +} +#hero h1 { + font-size: 2.5em; +} + +#hero h2 { + font-weight: 300; + font-family: 'Helvetica Neue','Helvetica','Arial','Lucida Grande','sans-serif'; + margin: 2em; +} +article { + width: 800px; + margin-left: auto; + margin-right: auto; + margin-top: 5em; + font-family: 'Georgia'; + text-align: justify; + font-size: 1.2em; +} +article p { + line-height: 140%; +} + +article > h1:first-child { + text-align: center; + margin: 2em; +} +.centered { + text-align: center; +} +.bottom-space { + margin-bottom: 7em; +} +pre { + border-radius: 3px; + padding: 0.5em; + border: 1px dotted #888; + background: #efefef; +} +*:focus { + outline: 0px none transparent; +} +textarea { + width: 800px; + border-radius: 5px; + font-family: Courier; + font-size: 1em; + height: 500px; +} +.hidden { + display: none; +} +.central-element { + width: 800px; + margin-left: auto; + margin-right: auto; +} +h1 { + font-size: 2em; +} +#dashed-line { + border-bottom: 1px dashed #888; + margin-top: 3em; + margin-bottom: 3em; +} +h1, h2, h3, h4, h5, h6 { + font-family: 'Noticia Text','PT Serif','Georgia'; +} diff --git a/src-cljs/main.cljs b/src-cljs/main.cljs deleted file mode 100644 index 5c5e59a..0000000 --- a/src-cljs/main.cljs +++ /dev/null @@ -1,94 +0,0 @@ -(ns NoteHub.main - (:require [goog.crypt.Md5 :as md5] - [goog.crypt :as crypt] - [NoteHub.crossover.lib :as lib])) - -(defn log - "Logs to console.log" - [text] - (.log js/console text)) - -(defn $ - "Returns DOM element by Id" - [id] - (.getElementById js/document (name id))) - -(defn val - "Returns the value of the element or sets the value if the value was provided" - ([element] (.-value element)) - ([element value] - (set! (.-value element) value))) - -(defn show - "show the element" - [element] - (set! (.-display (.-style element)) "block")) - -; frequently used selectors -(def $draft ($ :draft)) -(def $action ($ :action)) -(def $preview ($ :preview)) -(def $password ($ :password)) -(def $plain-password ($ :plain-password)) -(def $input-elems ($ :input-elems)) -(def $dashed-line ($ :dashed-line)) - -; Markdown Converter & Sanitizer instantiation -(def md-converter (Markdown.Converter.)) - -; instantiate & reset a MD5 hash digester -(def md5 (goog.crypt.Md5.)) -(.reset md5) - -; try to detect iOS -(def ios-detected? (.match (.-userAgent js/navigator) "(iPad|iPod|iPhone)")) - -(def timer nil) - -(def timerDelay - ; TODO: also test for Android - (if ios-detected? 800 400)) - -(defn update-preview - "Updates the preview" - [] - (do - (js/clearTimeout timer) - (let [content (val $draft) - ; the delay between the last typing and preview update is dynamic - ; and increases with the length of the text - delay (Math/min timerDelay (* timerDelay (/ (count content) 400)))] - (def timer - (js/setTimeout - #(do - (show $dashed-line) - (show $input-elems) - (set! (.-innerHTML $preview) - (.makeHtml md-converter content))) delay))))) - -; set focus to the draft textarea (if there is one) -(when $action - (do - (if (= "update" (val $action)) - (update-preview) - (val $draft "")) - ; focus setting is impossible in iOS, so we border the field instead - (if ios-detected? - (set! (.-className $draft) (str (.-className $draft) " ui-border")) - (.focus $draft)))) - -; show the preview & publish buttons as soon as the user starts typing. -(set! (.-onkeyup $draft) update-preview) - -; when the publish button is clicked, compute the hash of the entered text and -; provided session key and assign to the field session-value; -; moreover, compute the password hash as md5 before transmission -(set! (.-onclick ($ :publish-button)) - (fn [e] - (do - (.update md5 (val $plain-password)) - (val $plain-password nil) - (when (val $plain-password) - (val $password (crypt/byteArrayToHex (.digest md5)))) - (val ($ :session-value) - (lib/hash #(.charCodeAt % 0) (str (val $draft) (val ($ :session-key)))))))) diff --git a/src/NoteHub/crossover/lib.clj b/src/NoteHub/crossover/lib.clj deleted file mode 100644 index cd27197..0000000 --- a/src/NoteHub/crossover/lib.clj +++ /dev/null @@ -1,19 +0,0 @@ -(ns NoteHub.crossover.lib - (:refer-clojure :exclude [hash])) - -(defn hash - "A simple hash-function, which computes a hash from the text field - content and given session number. It is intended to be used as a spam - protection / captcha alternative (let's see whether spambots evaluate heavy JS). - (Probably doesn't work for UTF-16)" - [f s] - (let [short-mod #(mod % 32767) - char-codes (map f (remove #(contains? #{"\n" "\r"} %) (map str s))) - zip-with-index (map list char-codes (range))] - (reduce - #(short-mod (+ % - (short-mod (* (first %2) - ((if (odd? %) - bit-xor - bit-and) 16381 (second %2)))))) - 0 zip-with-index))) diff --git a/src/NoteHub/storage.clj b/src/NoteHub/storage.clj index 02f0df0..587eb38 100644 --- a/src/NoteHub/storage.clj +++ b/src/NoteHub/storage.clj @@ -41,8 +41,9 @@ (defn update-note "Updates a note with the given store key if the specified password is correct" [key text passwd] - (when (= passwd (redis/hget db password key)) - (redis/hset db note key text))) + (let [stored-password (redis/hget db password key)] + (when (and stored-password (= passwd stored-password)) + (redis/hset db note key text)))) (defn set-note "Creates a note with the given title and text in the given date namespace" diff --git a/src/NoteHub/views/common.clj b/src/NoteHub/views/common.clj index 57dd4c9..b6c2051 100644 --- a/src/NoteHub/views/common.clj +++ b/src/NoteHub/views/common.clj @@ -1,7 +1,6 @@ (ns NoteHub.views.common (:use [NoteHub.settings :only [get-message]] - [NoteHub.views.css] [noir.core :only [defpartial]] [noir.options :only [dev-mode?]] [hiccup.util :only [escape-html]] @@ -40,16 +39,16 @@ :rel "stylesheet" :type "text/css"}] ; generating the global CSS - [:style {:type "text/css"} (global-css params)] + [:link {:rel "stylesheet" :type "text/css" :href "/style.css"}] ; google analytics code should appear in prod mode only (if-not (dev-mode?) (include-js "/js/google-analytics.js"))] [:body content ; we only need JS during a new note creation, so don't render it otherwise (when (params :js) (html - (javascript-tag "var CLOSURE_NO_DEPS = true;") + (include-js "/js/md5.js") (include-js "/js/pagedown/Markdown.Converter.js") - (include-js "/cljs/main.js")))]))) + (include-js "/js/main.js")))]))) (defn layout "Generates the main html layout" diff --git a/src/NoteHub/views/css.clj b/src/NoteHub/views/css.clj deleted file mode 100644 index 4df09ff..0000000 --- a/src/NoteHub/views/css.clj +++ /dev/null @@ -1,179 +0,0 @@ -(ns NoteHub.views.css - (:use - [cssgen] - [cssgen.types :only [px %]] - [NoteHub.settings])) - -(defn- gen-fontlist [& fonts] - (apply str - (interpose "," - (map #(str "'" % "'") - (filter identity fonts))))) - -; CSS Mixins -(def page-width - (get-setting :page-width #(Integer/parseInt %) 800)) - -(def helvetica-neue - (mixin - :font-weight 300 - :font-family (gen-fontlist "Helvetica Neue" - "Helvetica" - "Arial" - "Lucida Grande" - "sans-serif"))) - -(def central-element - (mixin - :width (px page-width) - :margin-left "auto" - :margin-right "auto")) - -(defn thin-border [foreground] - (mixin :border-radius :3px - :border [:1px :solid foreground])) - -; Resolves the theme name & tone parameter to a concrete color -(defn- color [& keys] - (get-in {:dark {:background :#333 - :foreground :#ccc - :background-halftone :#444 - :foreground-halftone :#bbb - :link {:fresh :#6b8 - :visited :#496 - :hover :#7c9 }} - :solarized {:background :#073642 - :foreground :#93a1a1 - :background-halftone :#002b36 - :foreground-halftone :#eee8d5 - :link {:fresh :#cb4b16 - :visited :#b58900 - :hover :#dc322f }} - :default {:background :#fff - :foreground :#333 - :background-halftone :#efefef - :foreground-halftone :#888 - :link {:fresh :#097 - :visited :#054 - :hover :#0a8 }}} keys)) - -(defn global-css - "Generates the entire CSS rules of the app" - [params] - (let [theme (params :theme) - theme (if theme (keyword theme) :default) - header-fonts (gen-fontlist (params :header-font) "Noticia Text" "PT Serif" "Georgia") - text-fonts (gen-fontlist (params :text-font) "Georgia") - background (color theme :background) - foreground (color theme :foreground) - background-halftone (color theme :background-halftone) - foreground-halftone (color theme :foreground-halftone) - link-fresh (color theme :link :fresh) - link-visited (color theme :link :visited) - link-hover (color theme :link :hover)] - (css - (rule "a" - :color link-fresh - :text-decoration :none - :border-bottom [:1px :dotted] - (rule "&:hover" - :color link-hover) - (rule "&:visited" - :color link-visited)) - (rule "#draft" - :margin-bottom :3em) - (rule ".ui-border" - (thin-border foreground)) - (rule ".button" - :cursor :pointer) - (rule ".ui-elem" - helvetica-neue - (thin-border foreground) - :padding :0.3em - :opacity 0.8 - :font-size :1em - :background background) - (rule ".landing-button, table, tr, td, textarea, fieldset" - :border :none) - (rule ".landing-button" - :box-shadow [0 :2px :5px :#aaa] - :text-decoration :none - :font-size :1.5em - :background :#0a2 - :border-radius :10px - :padding :10px - helvetica-neue - (rule "&:hover" - :background :#0b2)) - (rule "#panel" - helvetica-neue - :position :fixed - :width (% 100) - :border-top [:1px :dotted foreground-halftone] - :background background-halftone - :padding :0.2em - :bottom :0px - :font-size :0.7em - :text-align :center - (rule "a" - :border :none)) - (rule "html, body" - :background background - :color foreground - :margin 0 - :padding 0) - (rule "#stats" - (rule "tr" - (rule "& > td:first-child" - :text-align :right))) - (rule ".helvetica-neue" - helvetica-neue) - (rule "#hero" - :padding-top :5em - :padding-bottom :5em - :text-align :center - (rule "h1" - :font-size :2.5em) - (rule "h2" - helvetica-neue - :margin :2em)) - (rule "article" - central-element - :margin-top :5em - :font-family text-fonts - :text-align :justify - :font-size :1.2em - (rule "p" - :line-height (% 140)) - (rule "& > h1:first-child" - :text-align :center - :margin :2em)) - (rule ".centered" - :text-align :center) - (rule ".bottom-space" - :margin-bottom :7em) - (rule "pre" - :border-radius :3px - :padding :0.5em - :border [:1px :dotted foreground-halftone] - :background background-halftone) - (rule "*:focus" - :outline [:0px :none :transparent]) - (rule "textarea" - :width (px page-width) - :border-radius :5px - :font-family :Courier - :font-size :1em - :height :500px) - (rule ".hidden" - :display :none) - (rule ".central-element" - central-element) - (rule "h1" - :font-size :2em) - (rule "#dashed-line" - :border-bottom [:1px :dashed foreground-halftone] - :margin-top :3em - :margin-bottom :3em) - (rule "h1, h2, h3, h4, h5, h6" - :font-family header-fonts)))) diff --git a/src/NoteHub/views/pages.clj b/src/NoteHub/views/pages.clj index 5e2cab5..366b290 100644 --- a/src/NoteHub/views/pages.clj +++ b/src/NoteHub/views/pages.clj @@ -1,6 +1,5 @@ (ns NoteHub.views.pages - (:require [NoteHub.crossover.lib :as lib] - [hiccup.util :as util]) + (:require [hiccup.util :as util]) (:use [NoteHub.storage] [NoteHub.settings] @@ -26,6 +25,22 @@ (defn md-to-html [md-text] (.markdownToHtml md-processor md-text)) +(defn get-hash + "A simple hash-function, which computes a hash from the text field + content and given session number. It is intended to be used as a spam + protection / captcha alternative. (Probably doesn't work for UTF-16)" + [s] + (let [short-mod #(mod % 32767) + char-codes (map #(.codePointAt % 0) (remove #(contains? #{"\n" "\r"} %) (map str s))) + zip-with-index (map list char-codes (range))] + (reduce + #(short-mod (+ % + (short-mod (* (first %2) + ((if (odd? %) + bit-xor + bit-and) 16381 (second %2)))))) + 0 zip-with-index))) + ; Sets a custom message for each needed HTTP status. ; The message to be assigned is extracted with a dynamically generated key (doseq [code [400 403 404 500]] @@ -151,7 +166,7 @@ ; is the hash code correct? valid-hash (try (= (Short/parseShort session-value) - (lib/hash #(.codePointAt % 0) (str draft session-key))) + (get-hash (str draft session-key))) (catch Exception e nil))] ; check whether the new note can be added (if (and valid-session valid-draft valid-hash)