diff --git a/project.clj b/project.clj index 2120500..c7974b4 100644 --- a/project.clj +++ b/project.clj @@ -8,6 +8,6 @@ ;; this line to .cake/config: jvm.opts = -Djava.security.policy=example.policy :jvm-opts ["-Djava.security.policy=example.policy""-Xmx80M"] :hooks [leiningen.fetch-js] - :main tryclojure.core) + :main tryclojure.server) diff --git a/src/tryclojure/models/eval.clj b/src/tryclojure/models/eval.clj new file mode 100644 index 0000000..da9b1f1 --- /dev/null +++ b/src/tryclojure/models/eval.clj @@ -0,0 +1,41 @@ +(ns tryclojure.models.eval + (:use [clojail.testers :only [secure-tester-without-def]] + [clojail.core :only [sandbox]] + [clojure.stacktrace :only [root-cause]]) + (:require [noir.session :as session]) + (:import java.io.StringWriter + java.util.concurrent.TimeoutException)) + +(defn eval-form [form sbox] + (with-open [out (StringWriter.)] + (let [result (sbox form {#'*out* out})] + {:expr form + :result [out result]}))) + +(defn eval-string [expr sbox] + (let [form (binding [*read-eval* false] (read-string expr))] + (eval-form form sbox))) + +(def try-clojure-tester + (into secure-tester-without-def + #{'tryclojure.core})) + +(defn make-sandbox [] + (sandbox try-clojure-tester + :timeout 2000 + :init '(do (use '[clojure.repl :only [doc]]) + (future (Thread/sleep 600000) + (-> *ns* .getName remove-ns))))) + +(defn find-sb [old] + (if-let [sb (get old "sb")] + old + (assoc old "sb" (make-sandbox)))) + +(defn eval-request [expr] + (try + (eval-string expr (get (session/swap! find-sb) "sb")) + (catch TimeoutException _ + {:error true :message "Execution Timed Out!"}) + (catch Exception e + {:error true :message (str (root-cause e))}))) \ No newline at end of file diff --git a/src/tryclojure/server.clj b/src/tryclojure/server.clj new file mode 100644 index 0000000..a606a15 --- /dev/null +++ b/src/tryclojure/server.clj @@ -0,0 +1,18 @@ +(ns tryclojure.server + (:use [ring.middleware.file :only [wrap-file]]) + (:require [noir.server :as server])) + +(server/add-middleware wrap-file (System/getProperty "user.dir")) +(server/load-views "src/tryclojure/views") + +(defn to-port [s] + (when-let [port s] (Long. port))) + +(defn tryclj [& [port]] + (server/start + (or (to-port port) + (to-port (System/getenv "PORT")) ;; For deploying to Heroku + 8801) + {:session-cookie-attrs {:max-age 600}})) + +(defn -main [& args] (tryclj (first args))) \ No newline at end of file diff --git a/src/tryclojure/views/eval.clj b/src/tryclojure/views/eval.clj new file mode 100644 index 0000000..782e40e --- /dev/null +++ b/src/tryclojure/views/eval.clj @@ -0,0 +1,16 @@ +(ns tryclojure.views.eval + (:use [noir.core :only [defpage]] + [noir.response :only [json]] + [tryclojure.models.eval :only [eval-request]])) + +(defpage "/eval.json" {:keys [expr jsonp]} + (update-in + (json + (let [{:keys [expr result error message] :as res} (eval-request expr)] + (if error + res + (let [[out res] result] + {:expr (pr-str expr) + :result (str out (pr-str res))})))) + [:body] + #(if jsonp (str jsonp "(" % ")") %))) \ No newline at end of file diff --git a/src/tryclojure/core.clj b/src/tryclojure/views/home.clj similarity index 63% rename from src/tryclojure/core.clj rename to src/tryclojure/views/home.clj index 4932813..db6f1a4 100644 --- a/src/tryclojure/core.clj +++ b/src/tryclojure/views/home.clj @@ -1,15 +1,6 @@ -(ns tryclojure.core - (:use [hiccup form-helpers page-helpers] - ring.middleware.file - noir.core - [noir.response :only [json]] - [clojure.stacktrace :only [root-cause]] - [clojail.core :only [sandbox eagerly-consume]] - [clojail.testers :only [secure-tester-without-def]]) - (:require [noir.server :as server] - [noir.session :as session]) - (:import java.io.StringWriter - java.util.concurrent.TimeoutException)) +(ns tryclojure.views.home + (:use [noir.core :only [defpartial defpage]] + [hiccup form-helpers page-helpers])) (defpartial links [] (unordered-list @@ -104,66 +95,3 @@ (defpage "/links" [] (links)) - -(defpage [:post "/tutorial"] {n :n} - (slurp (str "resources/public/tutorial/page" n ".html"))) - -(defn eval-form [form sbox] - (with-open [out (java.io.StringWriter.)] - (let [result (sbox form {#'*out* out})] - {:expr form - :result [out result]}))) - -(defn eval-string [expr sbox] - (let [form (binding [*read-eval* false] (read-string expr))] - (eval-form form sbox))) - -(def try-clojure-tester - (into secure-tester-without-def - #{'tryclojure.core})) - -(defn make-sandbox [] - (sandbox try-clojure-tester - :timeout 2000 - :init '(do (use '[clojure.repl :only [doc]]) - (future (Thread/sleep 600000) - (-> *ns* .getName remove-ns))))) - -(defn find-sb [old] - (if-let [sb (get old "sb")] - old - (assoc old "sb" (make-sandbox)))) - -(defn eval-request [expr] - (try - (eval-string expr (get (session/swap! find-sb) "sb")) - (catch TimeoutException _ - {:error true :message "Execution Timed Out!"}) - (catch Exception e - {:error true :message (str (root-cause e))}))) - -(defpage "/eval.json" {:keys [expr jsonp]} - (update-in - (json - (let [{:keys [expr result error message] :as res} (eval-request expr)] - (if error - res - (let [[out res] result] - {:expr (pr-str expr) - :result (str out (pr-str res))})))) - [:body] - #(if jsonp (str jsonp "(" % ")") %))) - -(server/add-middleware wrap-file (System/getProperty "user.dir")) - -(defn to-port [s] - (when-let [port s] (Long. port))) - -(defn tryclj [& [port]] - (server/start - (or (to-port port) - (to-port (System/getenv "PORT")) ;; For deploying to Heroku - 8801) - {:session-cookie-attrs {:max-age 600}})) - -(defn -main [& args] (tryclj (first args))) \ No newline at end of file diff --git a/src/tryclojure/views/tutorial.clj b/src/tryclojure/views/tutorial.clj new file mode 100644 index 0000000..69538ad --- /dev/null +++ b/src/tryclojure/views/tutorial.clj @@ -0,0 +1,5 @@ +(ns tryclojure.views.tutorial + (:use [noir.core :only [defpage]])) + +(defpage [:post "/tutorial"] {n :n} + (slurp (str "resources/public/tutorial/page" n ".html"))) \ No newline at end of file