From ab9109b0164daea036d78cd0f643893cdb4d52fd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=96zg=C3=BCr=20Kesim?= Date: Sun, 25 Nov 2018 13:55:47 +0100 Subject: [PATCH 1/4] added support for povray --- index.html | 6 +++++- main.go | 52 ++++++++++++++++++++++++++++++++++++++---------- static/povray.js | 1 + tools.json | 14 +++++++++++++ 4 files changed, 62 insertions(+), 11 deletions(-) create mode 120000 static/povray.js diff --git a/index.html b/index.html index f4cd42d..37ab4aa 100644 --- a/index.html +++ b/index.html @@ -161,7 +161,11 @@ function run() { req.onreadystatechange = function() { switch (req.status) { case 200: - output.innerHTML = req.responseText; + if (req.getResponseHeader("Content-Type") === "img/png") { + output.innerHTML = ''; + } else { + output.innerHTML = req.responseText; + } break; case 400: output.innerHTML = '
'+req.responseText+'
'; diff --git a/main.go b/main.go index c3afed3..6d6278f 100644 --- a/main.go +++ b/main.go @@ -29,6 +29,8 @@ type Tool struct { Name string Cmd string Args []string + NeedsFile bool + EncodeBase64 bool Suffix string Description string Documentation map[string]string @@ -36,31 +38,61 @@ type Tool struct { BgColor string } -func (t Tool) execute(in io.Reader, w http.ResponseWriter) { +func (t *Tool) execute(in io.Reader, w http.ResponseWriter) { + var args []string + + if t.NeedsFile { + tmpf, e := ioutil.TempFile(".", "*"+t.Suffix) + if e != nil { + log.Printf("couldn't create tmp-file: %v\n", e) + http.Error(w, e.Error(), http.StatusInternalServerError) + return + } else if _, e = io.Copy(tmpf, in); e != nil { + log.Printf("couldn't write to tmp-file: %v\n", e) + http.Error(w, e.Error(), http.StatusInternalServerError) + return + } + defer os.Remove(tmpf.Name()) + log.Printf("using tempfile: %q\n", tmpf.Name()) + + args = []string{} + args = append(args, t.Args...) + args = append(args, tmpf.Name()) + } else { + args = t.Args + } + var ( - cmd = exec.Command(t.Cmd, t.Args...) + cmd = exec.Command(t.Cmd, args...) err, buf = &bytes.Buffer{}, &bytes.Buffer{} ) - cmd.Stdin = in + if !t.NeedsFile { + cmd.Stdin = in + } cmd.Stderr = err cmd.Stdout = buf if e := cmd.Run(); e == nil { - io.Copy(w, buf) + if t.EncodeBase64 { + w.Header().Add("Content-Type", "img/png") + io.Copy(base64.NewEncoder(base64.StdEncoding, w), buf) + } else { + io.Copy(w, buf) + } } else { log.Printf("%s returned error\n", t.Name) http.Error(w, err.String(), http.StatusBadRequest) } } -func (t Tool) compile() func(http.ResponseWriter, *http.Request) { +func (t *Tool) compile() func(http.ResponseWriter, *http.Request) { return func(w http.ResponseWriter, r *http.Request) { t.execute(r.Body, w) } } -func (t Tool) svg() func(http.ResponseWriter, *http.Request) { +func (t *Tool) svg() func(http.ResponseWriter, *http.Request) { return func(w http.ResponseWriter, r *http.Request) { name := filepath.Base(r.URL.Path) if file, err := os.Open(filepath.Join(*savedir, name+t.Suffix)); err != nil { @@ -75,7 +107,7 @@ func (t Tool) svg() func(http.ResponseWriter, *http.Request) { const maxSnippetSize = 64 * 1024 -func (t Tool) save() func(http.ResponseWriter, *http.Request) { +func (t *Tool) save() func(http.ResponseWriter, *http.Request) { return func(w http.ResponseWriter, r *http.Request) { body, err := ioutil.ReadAll(io.LimitReader(r.Body, maxSnippetSize)) if err != nil { @@ -112,7 +144,7 @@ func (t Tool) save() func(http.ResponseWriter, *http.Request) { } } -func (t Tool) load() func(http.ResponseWriter, *http.Request) { +func (t *Tool) load() func(http.ResponseWriter, *http.Request) { return func(w http.ResponseWriter, r *http.Request) { name := filepath.Base(r.URL.Path) if file, err := os.Open(filepath.Join(*savedir, name+t.Suffix)); err != nil { @@ -125,7 +157,7 @@ func (t Tool) load() func(http.ResponseWriter, *http.Request) { } } -func (t Tool) index(tmpl *template.Template, data interface{}) func(http.ResponseWriter, *http.Request) { +func (t *Tool) index(tmpl *template.Template, data interface{}) func(http.ResponseWriter, *http.Request) { return func(w http.ResponseWriter, r *http.Request) { err := tmpl.ExecuteTemplate(w, "index.html", map[string]interface{}{"Tools": data, "Cur": t}) if err != nil { @@ -135,7 +167,7 @@ func (t Tool) index(tmpl *template.Template, data interface{}) func(http.Respons } func main() { - var tools = []Tool{} + var tools = []*Tool{} var tmpl *template.Template flag.Parse() diff --git a/static/povray.js b/static/povray.js new file mode 120000 index 0000000..e382383 --- /dev/null +++ b/static/povray.js @@ -0,0 +1 @@ +dot.js \ No newline at end of file diff --git a/tools.json b/tools.json index 9f3b3fe..2fa6d1f 100644 --- a/tools.json +++ b/tools.json @@ -25,5 +25,19 @@ "https://ece.uwaterloo.ca/~aplevich/dpic": "Get DPIC from here" }, "Example": ".PS\n\nbox \"foo\"; arrow ->; box \"bar\"\n\n.PE" + }, + { + "Name": "povray", + "Cmd": "povray", + "Args": ["+O-", "-D"], + "Suffix": ".pov", + "NeedsFile": true, + "EncodeBase64": true, + "Description": "Povray, raytracer", + "BgColor": "Orange", + "Documentation": { + "http://povray.org/documentation/3.7.0/index.html": "POV-Ray for Unix" + }, + "Example": "#include \"colors.inc\"\n#include \"woods.inc\"\n#include \"glass.inc\"\ncylinder {\n\t<-2,-2,0.5>, <-2,1,0.5>, 1\n\tpigment {color Red}\n}\nsphere {\n\t<0,1,1>, 1\n\tpigment {color Blue }\n}\nbox {\n\t<-3,-1,-1>, <1,-0.5, 2>\n\tpigment {\n\t\tCol_Glass_Winebottle\n\t}\n}\nbackground { color Gray60 }\nlight_source {<0, 5, -3> color White }\nlight_source {<-2, 2, 0.5> color Yellow }\ncamera {\n\tlocation <0, 2, -6>\n\tangle 50 right x\n\tlook_at\n\t<-1, 0, 0>\n}\n" } ] From d50b0e29c6263a076a0558350219b3a9a01fdf38 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=96zg=C3=BCr=20Kesim?= Date: Sun, 25 Nov 2018 14:47:43 +0100 Subject: [PATCH 2/4] less verbose on tempfiles --- main.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/main.go b/main.go index 6d6278f..24cb4a7 100644 --- a/main.go +++ b/main.go @@ -53,7 +53,7 @@ func (t *Tool) execute(in io.Reader, w http.ResponseWriter) { return } defer os.Remove(tmpf.Name()) - log.Printf("using tempfile: %q\n", tmpf.Name()) + // log.Printf("using tempfile: %q\n", tmpf.Name()) args = []string{} args = append(args, t.Args...) From 4ceca4f3d3ce3b24429f0b6c6aec2a5ada432fff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=96zg=C3=BCr=20Kesim?= Date: Mon, 26 Nov 2018 07:44:06 +0100 Subject: [PATCH 3/4] switch on antialiasing --- tools.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools.json b/tools.json index 2fa6d1f..9735acc 100644 --- a/tools.json +++ b/tools.json @@ -29,7 +29,7 @@ { "Name": "povray", "Cmd": "povray", - "Args": ["+O-", "-D"], + "Args": ["+O-", "-D", "+A0.9", "+R3"], "Suffix": ".pov", "NeedsFile": true, "EncodeBase64": true, From 1e3b329150d6c259ba058f8d8f2e1b3fd4bb525d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=96zg=C3=BCr=20Kesim?= Date: Mon, 26 Nov 2018 07:54:18 +0100 Subject: [PATCH 4/4] use 'ContentType' rather than 'EncodeBase64' in tools.json --- main.go | 6 +++--- tools.json | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/main.go b/main.go index 24cb4a7..07e15b1 100644 --- a/main.go +++ b/main.go @@ -30,7 +30,7 @@ type Tool struct { Cmd string Args []string NeedsFile bool - EncodeBase64 bool + ContentType string Suffix string Description string Documentation map[string]string @@ -74,8 +74,8 @@ func (t *Tool) execute(in io.Reader, w http.ResponseWriter) { cmd.Stdout = buf if e := cmd.Run(); e == nil { - if t.EncodeBase64 { - w.Header().Add("Content-Type", "img/png") + if t.ContentType != "" { + w.Header().Add("Content-Type", t.ContentType) io.Copy(base64.NewEncoder(base64.StdEncoding, w), buf) } else { io.Copy(w, buf) diff --git a/tools.json b/tools.json index 9735acc..f19fa5d 100644 --- a/tools.json +++ b/tools.json @@ -32,7 +32,7 @@ "Args": ["+O-", "-D", "+A0.9", "+R3"], "Suffix": ".pov", "NeedsFile": true, - "EncodeBase64": true, + "ContentType": "img/png", "Description": "Povray, raytracer", "BgColor": "Orange", "Documentation": {