Skip to content

Commit

Permalink
Update deps and move to noir. Running on noir, but sandboxing isn't d…
Browse files Browse the repository at this point in the history
…one yet. def sandboxing has been totally changed.
  • Loading branch information
Raynes committed Oct 29, 2011
1 parent d89a89e commit 30f3f01
Show file tree
Hide file tree
Showing 2 changed files with 93 additions and 156 deletions.
11 changes: 3 additions & 8 deletions project.clj
Original file line number Original file line Diff line number Diff line change
@@ -1,11 +1,6 @@
(defproject tryclojure "0.1.0-SNAPSHOT" (defproject tryclojure "0.1.0-SNAPSHOT"
:description "A simple web-based Clojure REPL for trying out Clojure without having to install it." :description "A simple web-based Clojure REPL for trying out Clojure without having to install it."
:dependencies [[org.clojure/clojure "1.2.0"] :dependencies [[org.clojure/clojure "1.3.0"]
[org.clojure/clojure-contrib "1.2.0"] [noir "1.2.0"]
[net.cgrand/moustache "1.0.0-SNAPSHOT" :exclusions [org.clojure/clojure]]
[ring "0.3.3"]
[commons-lang/commons-lang "2.5"] [commons-lang/commons-lang "2.5"]
[clojail "0.4.0-SNAPSHOT"] [clojail "0.4.6-beta2"]])
[hiccup "0.2.7"]]
:dev-dependencies [[swank-clojure "1.2.1"]
[ring/ring-devel "0.3.3"]])
238 changes: 90 additions & 148 deletions src/tryclojure/core.clj
Original file line number Original file line Diff line number Diff line change
@@ -1,21 +1,82 @@
(ns tryclojure.core (ns tryclojure.core
(:use ring.adapter.jetty (:use ring.adapter.jetty
[hiccup core form-helpers page-helpers] [hiccup form-helpers page-helpers]
[ring.middleware reload stacktrace params file session] [ring.middleware reload stacktrace params file session]
net.cgrand.moustache noir.core
[noir.response :only [json]]
[clojure.stacktrace :only [root-cause]] [clojure.stacktrace :only [root-cause]]
[clojail core testers] [clojail.core :only [sandbox]]
[clojure.set :only [difference]]) [clojail.testers :only [secure-tester-without-def]])
(:require [clojure.contrib.json :as json]) (:require [noir.server :as server])
(:import java.io.StringWriter (:import java.io.StringWriter
java.util.concurrent.TimeoutException)) java.util.concurrent.TimeoutException))


(def sb-tester (difference secure-tester #{'def})) (defpartial links []

(unordered-list
(def state-tester #{'def 'def* 'ensure 'ref-set 'alter 'commute 'swap! 'compare-and-set!}) [(link-to "http://clojure.org" "The official Clojure website")
(link-to "http://dev.clojure.org/display/doc/Getting+Started" "Getting started with Clojure")
(link-to "http://groups.google.com/group/clojure" "Clojure mailing list")
(link-to "http://java.ociweb.com/mark/clojure/article.html" "A comprehensive Clojure tutorial")
(link-to "http://joyofclojure.com/" "The Joy of Clojure: a book by Michael Fogus and Chris Houser")
(link-to "http://disclojure.org" "Disclojure")
(link-to "http://planet.clojure.in" "Planet Clojure")]))

(defpartial bottom-html []
[:p.bottom
"This site is still under construction. I can't promise everything will work correctly."
" You can find the site's source and such on its " (link-to "http://github.com/Raynes/tryclojure" "github")
" page."]
[:p.bottom
"Please note that this REPL is sandboxed, so you wont be able to do everything in it "
"that you would in a local unsandboxed REPL. Keep in mind that this site is designed for "
"beginners to try out Clojure and not necessarily as a general-purpose server-side REPL."]
[:p.bottom
"TryClojure is written in Clojure and JavaScript (JQuery), powered by "
(link-to "https://github.com/flatland/clojail" "clojail")
" and Chris Done's "
(link-to "https://github.com/chrisdone/jquery-console" "jquery-console")]
[:p.bottom "Design by " (link-to "http://apgwoz.com" "Andrew Gwozdziewyc")])

(defpartial home-text []
[:p.bottom
"Welcome to Try Clojure. Above, you have a Clojure REPL. You can type expressions and see "
"their results right here in your browser. We also have a brief tutorial to give you a "
"taste of Clojure. Try it out by typing <code class=\"expr\">tutorial</code> in the console!"])


(defn has-state? [form] (defpartial fire-html []
(check-form form state-tester)) (:html4 doctype)
[:head
(include-css "/resources/public/css/tryclojure.css")
(include-js "/resources/public/javascript/jquery-1.4.2.min.js"
"/resources/public/javascript/jquery.console.js"
"/resources/public/javascript/tryclojure.js")
[:title "Try Clojure"]]
[:body
[:div#wrapper
[:div#content
[:div#header
[:h1
[:span.logo-try "Try"] " "
[:span.logo-clojure "Clo" [:em "j"] "ure"]]]
[:div#container
[:div#console.console]
[:div#buttons
[:a#links.buttons "links"]
[:a#about.buttons.last "about"]]
[:div#changer (home-text)]]
[:div.footer
[:p.bottom "©2011 Anthony Grimes (Raynes) and contributors"]
[:p.bottom "Domain kindly paid for by "
(link-to "http://blog.licenser.net" "Heinz N. Gies")]]]]])

(defpage "/" []
(fire-html))

(defpage "/about" []
(bottom-html))

(defpage "/links" []
(links))


(defn eval-form [form sbox] (defn eval-form [form sbox]
(with-open [out (java.io.StringWriter.)] (with-open [out (java.io.StringWriter.)]
Expand All @@ -27,147 +88,28 @@
(let [form (binding [*read-eval* false] (read-string expr))] (let [form (binding [*read-eval* false] (read-string expr))]
(eval-form form sbox))) (eval-form form sbox)))


(defn eval-request [{params :params {history :history} :session}] (defn eval-request [expr]
(let [sbox (sandbox sb-tester :timeout 3000)] (let [sbox (sandbox secure-tester-without-def :timeout 3000)]
(try (try
;; re-eval history forms (eval-string expr sbox)
(doseq [form history] (eval-form form sbox))
;; eval request parameter
(eval-string (params "expr") sbox)
(catch OutOfMemoryError _
{:error true :message "Out of memory error was thrown. Cleaning up all defs."})
(catch TimeoutException _ (catch TimeoutException _
{:error true :message "Execution Timed Out!"}) {:error true :message "Execution Timed Out!"})
(catch Exception e (catch Exception e
{:error true :message (.getMessage (root-cause e))})))) {:error true :message (.getMessage (root-cause e))}))))


(def links (defpage "/eval.json" {:keys [expr]}
(html (unordered-list (prn "expr")
[(link-to "http://clojure.org" "The official Clojure website") (json
(link-to "http://dev.clojure.org/display/doc/Getting+Started" "Getting started with Clojure") (let [{:keys [expr result error message] :as res} (eval-request expr)]
(link-to "http://groups.google.com/group/clojure" "Clojure mailing list") (if error
(link-to "http://java.ociweb.com/mark/clojure/article.html" "A comprehensive Clojure tutorial") res
(link-to "http://joyofclojure.com/" "The Joy of Clojure: a book by Michael Fogus and Chris Houser") (let [[out res] result]
(link-to "http://www.pragprog.com/titles/shcloj/programming-clojure" "Programming Clojure, a book by Stuart Halloway") {:expr (pr-str expr)
(link-to "http://disclojure.org" "Disclojure") :result (str out (pr-str res))})))))
(link-to "http://planet.clojure.in" "Planet Clojure")])))

(server/add-middleware wrap-session)
(def bottom-html (server/add-middleware wrap-file (System/getProperty "user.dir"))
(html [:p.bottom (server/add-middleware wrap-params)
"This site is still under construction. I can't promise everything will work correctly." (server/add-middleware wrap-stacktrace)
" You can find the site's source and such on its " (link-to "http://github.com/Raynes/tryclojure" "github")
" page."] (defn tryclj [] (server/start 8801))
[:p.bottom
"Please note that this REPL is sandboxed, so you wont be able to do everything in it "
"that you would in a local unsandboxed REPL. Keep in mind that this site is designed for "
"beginners to try out Clojure and not necessarily as a general-purpose server-side REPL."]
[:p.bottom
"TryClojure is written in Clojure and JavaScript (JQuery), powered by "
(link-to "http://github.com/Raynes/clojail" "clojail")
" and Chris Done's "
(link-to "http://github.com/chrisdone/jquery-console" "jquery-console")]
[:p.bottom "Design by " (link-to "http://apgwoz.com" "Andrew Gwozdziewyc")]))

(def home-text
[:p.bottom
"Welcome to Try Clojure. Above, you have a Clojure REPL. You can type expressions and see "
"their results right here in your browser. We also have a brief tutorial to give you a "
"taste of Clojure. Try it out by typing <code class=\"expr\">tutorial</code> in the console!"])

(def fire-html
(html
(:html4 doctype)
[:head
(include-css "/resources/public/css/tryclojure.css")
(include-js "/resources/public/javascript/jquery-1.4.2.min.js"
"/resources/public/javascript/jquery.console.js"
"/resources/public/javascript/tryclojure.js")
[:title "Try Clojure"]]
[:body
[:div#wrapper
[:div#content
[:div#header
[:h1
[:span.logo-try "Try"] " "
[:span.logo-clojure "Clo" [:em "j"] "ure"]]]
[:div#container
[:div#console.console]
[:div#buttons
[:a#links.buttons "links"]
[:a#about.buttons.last "about"]]
[:div#changer home-text]]
[:div.footer
[:p.bottom "©2011 Anthony Grimes (Raynes) and contributors"]
[:p.bottom "Domain kindly paid for by "
(link-to "http://blog.licenser.net" "Heinz N. Gies")]]]]]))

(defn handler [{session :session}]
{:status 200
:headers {"Content-Type" "text/html"}
:session session
:body fire-html})

(defn about-handler [{session :session}]
{:status 200
:headers {"Content-Type" "text/html"}
:session session
:body bottom-html})

(defn link-handler [{session :session}]
{:status 200
:headers {"Content-Type" "text/html"}
:session session
:body links})

(def ^{:private true}
eval-response-defaults
{:status 200
:headers {"Content-Type" "application/json"}})

(defn eval-handler [request]
(let [{:keys [expr result error message] :as res} (eval-request request)
history (get-in request [:session :history] [])]
(if error
(merge eval-response-defaults
{:session (:session request)
:body (json/json-str res)})
(let [[out res] result]
(merge eval-response-defaults
{:session {:history (conj history expr)}
:body (json/json-str {:expr (pr-str expr)
:result (str out (pr-str res))})})))))

(defn tutorial-handler [{{n "n"} :params session :session :as res}]
{:status 200
:headers {"Content-Type" "application/html"}
:session session
:body (slurp (str "resources/public/tutorial/page" n ".html"))})

(defn- max-history [max history]
(if (> (count history) max)
(drop 1 history)
history))

(defn wrap-post-history [handler]
(fn [request]
(let [response (handler request)]
(->> (get-in response [:session :history] [])
(max-history 5)
(filter has-state?)
vec
(assoc-in response [:session :history])))))

(def clojureroutes
(app
(wrap-session)
(wrap-post-history)
(wrap-file (System/getProperty "user.dir"))
(wrap-params)
(wrap-stacktrace)
["links"] link-handler
["about"] about-handler
["eval.json"] eval-handler
["tutorial"] tutorial-handler
[""] handler))

(defn tryclj [] (run-jetty #'clojureroutes {:port 8801}))

0 comments on commit 30f3f01

Please sign in to comment.