Jelajahi Sumber

Remove the experimental web UI.

It has not been actively developed for a long time and has a vulnerability:
https://github.com/elves/elvish/security/advisories/GHSA-fpv6-f8jw-rc3r
Qi Xiao 2 tahun lalu
induk
melakukan
ccc2750037
4 mengubah file dengan 0 tambahan dan 457 penghapusan
  1. 0 22
      cmd/withweb/elvish/main.go
  2. 0 233
      pkg/web/main.html.go
  3. 0 183
      pkg/web/web.go
  4. 0 19
      pkg/web/web_test.go

+ 0 - 22
cmd/withweb/elvish/main.go

@@ -1,22 +0,0 @@
-// Command elvish is an alternative main program of Elvish that includes the web
-// subprogram.
-package main
-
-import (
-	"os"
-
-	"src.elv.sh/pkg/buildinfo"
-	"src.elv.sh/pkg/daemon"
-	"src.elv.sh/pkg/daemon/client"
-	"src.elv.sh/pkg/prog"
-	"src.elv.sh/pkg/shell"
-	"src.elv.sh/pkg/web"
-)
-
-func main() {
-	os.Exit(prog.Run(
-		[3]*os.File{os.Stdin, os.Stdout, os.Stderr}, os.Args,
-		prog.Composite(
-			buildinfo.Program, daemon.Program, web.Program,
-			shell.Program{ActivateDaemon: client.Activate})))
-}

+ 0 - 233
pkg/web/main.html.go

@@ -1,233 +0,0 @@
-package web
-
-const mainPageHTML = `<html>
-
-  <body class="light">
-    <div id="content">
-      <div id="scrollback">
-        <div id="progress"></div>
-      </div>
-
-      <div id="cmd" class="cmd">
-        <span id="prompt" class="prompt">&gt;&gt;</span>
-        <textarea id="buffer" class="buffer" rows="1"></textarea>
-      </div>
-
-      <div id="theme-switchers" class="flex">
-        <span class="theme-switcher" id="dark-theme">dark</span>
-        <span class="theme-switcher" id="light-theme">light</span>
-      </div>
-
-    </div>
-  </body>
-
-  <style>
-    /* Colors are taken from Material palette. */
-
-    /* Global styles */
-
-    * {
-      margin: 0;
-      padding: 0;
-      font: 12pt monospace;
-    }
-
-    #content {
-      margin: 20px;
-      padding: 20px;
-    }
-
-    /* Scrollback */
-
-    .exception {
-      font-weight: bold;
-    }
-
-    .server-error {
-      font-style: italic;
-    }
-
-    /* Command line */
-
-    .cmd {
-      display: flex;
-      width: 100%;
-    }
-
-    .cmd > .prompt {
-      display: inline-block;
-      margin-right: 1em;
-    }
-
-    .cmd > .buffer {
-      flex: 1;
-    }
-
-    /* Theme switcher */
-
-    #theme-switchers {
-      display: flex;
-      margin-top: 0.4em;
-    }
-
-    .theme-switcher {
-      cursor: pointer;
-      padding: 0 1em;
-      border: 1px solid;
-    }
-
-    #light-theme {
-      color: black;
-      background-color: white;
-      border-color: black;
-    }
-
-    #dark-theme {
-      color: white;
-      background-color: black;
-      border-color: white;
-    }
-
-    /* Color schemes. Color values from Material palette. */
-
-    body.light {
-      background: #EEEEEE; /* grey 200 */
-    }
-
-    .light * {
-      color: black;
-      background: white;
-    }
-
-    .light #content {
-      background: white;
-    }
-
-    .light .cmd > .prompt {
-      color: #1565C0; /* blue 800 */
-    }
-
-    .light .cmd > #prompt {
-      color: #2E7D32; /* green 800 */
-    }
-
-    .light .error {
-      color: #C62828; /* red 800 */
-    }
-
-
-    .dark * {
-      color: white;
-      background: black;
-    }
-
-    body.dark {
-      background: #212121; /* grey 900 */
-    }
-
-    .dark #content {
-      background: black;
-    }
-
-    .dark .cmd > .prompt {
-      color: #90CAF9; /* blue 200 */
-    }
-
-    .dark .cmd > #prompt {
-      color: #A5D6A7; /* green 200 */
-    }
-
-    .dark .error {
-      color: #EF9A9A; /* red 200 */
-    }
-
-  </style>
-
-  <script>
-    // TODO(xiaq): Stream results.
-    var $prompt = document.getElementById('prompt'),
-        $buffer = document.getElementById('buffer'),
-        $scrollback = document.getElementById('scrollback'),
-        $progress = document.getElementById('progress');
-
-    /* Theme switchers. */
-    document.getElementById('dark-theme').onclick = function() {
-      document.body.className = 'dark';
-    };
-
-    document.getElementById('light-theme').onclick = function() {
-      document.body.className = 'light';
-    };
-
-    $buffer.addEventListener('keypress', function(e) {
-      if (e.keyCode == 13 &&
-          !e.shiftKey && !e.ctrlKey && !e.altKey && !e.metaKey) {
-        e.preventDefault();
-        execute();
-      }
-    });
-
-    function execute() {
-      var code = $buffer.value;
-      addToScrollbackInner(freezeCmd());
-      $buffer.value = '';
-      $progress.innerText = 'executing...';
-
-      var req = new XMLHttpRequest();
-      req.onloadend = function() {
-        $progress.innerText = '';
-      };
-      req.onload = function() {
-        var res = JSON.parse(req.responseText);
-        addToScrollback('output', res.OutBytes);
-        if (res.OutValues) {
-          for (var v of res.OutValues) {
-            addToScrollback('output-value', v);
-          }
-        }
-        addToScrollback('error', res.ErrBytes);
-        addToScrollback('error exception', res.Err);
-      };
-      req.onerror = function() {
-        addToScrollback('error server-error', req.responseText
-          || req.statusText
-          || (req.status == req.UNSENT && "lost connection")
-          || "unknown error");
-      };
-      req.open('POST', '/execute');
-      req.send(code);
-    }
-
-    function addToScrollback(className, innerText) {
-      var div = document.createElement('div');
-      div.className = className;
-      div.innerText = innerText;
-
-      addToScrollbackInner(div);
-    }
-
-    function addToScrollbackInner(element) {
-      $scrollback.insertBefore(element, $progress);
-      window.scrollTo(0, document.body.scrollHeight);
-    }
-
-    function freezeCmd() {
-      var cmd = document.createElement('div'),
-          prompt = document.createElement('span'),
-          buffer = document.createElement('span');
-      cmd.className = 'cmd';
-      prompt.className = 'prompt';
-      prompt.innerText = $prompt.innerText;
-      buffer.className = 'buffer';
-      buffer.innerText = $buffer.value;
-      cmd.appendChild(prompt);
-      cmd.appendChild(buffer);
-      return cmd;
-    }
-
-  </script>
-
-</html>
-`
-
-// vim: se ft=html si et sw=2 ts=2 sts=2:

+ 0 - 183
pkg/web/web.go

@@ -1,183 +0,0 @@
-// Package web is the entry point for the backend of the web interface of
-// Elvish.
-package web
-
-import (
-	"encoding/json"
-	"fmt"
-	"io"
-	"log"
-	"net/http"
-	"os"
-
-	"src.elv.sh/pkg/eval"
-	"src.elv.sh/pkg/parse"
-	"src.elv.sh/pkg/prog"
-	"src.elv.sh/pkg/shell"
-)
-
-// Program is the web subprogram.
-var Program prog.Program = program{}
-
-type program struct{}
-
-func (program) Run(fds [3]*os.File, f *prog.Flags, args []string) error {
-	if !f.Web {
-		return prog.ErrNotSuitable
-	}
-	if len(args) > 0 {
-		return prog.BadUsage("arguments are not allowed with -web")
-	}
-	if f.CodeInArg {
-		return prog.BadUsage("-c cannot be used together with -web")
-	}
-	p := Web{Port: f.Port}
-	return p.Main(fds, nil)
-}
-
-type Web struct {
-	Port int
-}
-
-type httpHandler struct {
-	ev *eval.Evaler
-}
-
-type ExecuteResponse struct {
-	OutBytes  string
-	OutValues []interface{}
-	ErrBytes  string
-	Err       string
-}
-
-func (web *Web) Main(fds [3]*os.File, _ []string) error {
-	restore := shell.IncSHLVL()
-	defer restore()
-	ev := shell.MakeEvaler(fds[2])
-
-	h := httpHandler{ev}
-
-	http.HandleFunc("/", h.handleMainPage)
-	http.HandleFunc("/execute", h.handleExecute)
-	addr := fmt.Sprintf("localhost:%d", web.Port)
-	log.Println("going to listen", addr)
-	err := http.ListenAndServe(addr, nil)
-
-	log.Println(err)
-	return nil
-}
-
-func (h httpHandler) handleMainPage(w http.ResponseWriter, r *http.Request) {
-	_, err := w.Write([]byte(mainPageHTML))
-	if err != nil {
-		log.Println("cannot write response:", err)
-	}
-}
-
-func (h httpHandler) handleExecute(w http.ResponseWriter, r *http.Request) {
-	bytes, err := io.ReadAll(r.Body)
-	if err != nil {
-		log.Println("cannot read request body:", err)
-		return
-	}
-	code := string(bytes)
-
-	outBytes, outValues, errBytes, err := evalAndCollect(h.ev, code)
-	errText := ""
-	if err != nil {
-		errText = err.Error()
-	}
-	responseBody, err := json.Marshal(
-		&ExecuteResponse{string(outBytes), outValues, string(errBytes), errText})
-	if err != nil {
-		log.Println("cannot marshal response body:", err)
-	}
-
-	_, err = w.Write(responseBody)
-	if err != nil {
-		log.Println("cannot write response:", err)
-	}
-}
-
-const (
-	outFileBufferSize = 1024
-	outChanBufferSize = 32
-)
-
-// evalAndCollect evaluates a piece of code with null stdin, and stdout and
-// stderr connected to pipes (value part of stderr being a blackhole), and
-// return the results collected on stdout and stderr, and the possible error
-// that occurred.
-func evalAndCollect(ev *eval.Evaler, code string) (
-	outBytes []byte, outValues []interface{}, errBytes []byte, err error) {
-
-	outFile, chanOutBytes := makeBytesWriterAndCollect()
-	outChan, chanOutValues := makeValuesWriterAndCollect()
-	errFile, chanErrBytes := makeBytesWriterAndCollect()
-
-	ports := []*eval.Port{
-		eval.DummyInputPort,
-		{File: outFile, Chan: outChan},
-		{File: errFile, Chan: eval.BlackholeChan},
-	}
-	err = ev.Eval(
-		parse.Source{Name: "[web]", Code: code}, eval.EvalCfg{Ports: ports})
-
-	outFile.Close()
-	close(outChan)
-	errFile.Close()
-	return <-chanOutBytes, <-chanOutValues, <-chanErrBytes, err
-}
-
-// makeBytesWriterAndCollect makes an in-memory file that can be written to, and
-// the written bytes will be collected in a byte slice that will be put on a
-// channel as soon as the writer is closed.
-func makeBytesWriterAndCollect() (*os.File, <-chan []byte) {
-	r, w, err := os.Pipe()
-	// os.Pipe returns error only on resource exhaustion.
-	if err != nil {
-		panic(err)
-	}
-	chanCollected := make(chan []byte)
-
-	go func() {
-		var (
-			collected []byte
-			buf       [outFileBufferSize]byte
-		)
-		for {
-			n, err := r.Read(buf[:])
-			collected = append(collected, buf[:n]...)
-			if err != nil {
-				if err != io.EOF {
-					log.Println("error when reading output pipe:", err)
-				}
-				break
-			}
-		}
-		r.Close()
-		chanCollected <- collected
-	}()
-
-	return w, chanCollected
-}
-
-// makeValuesWriterAndCollect makes a Value channel for writing, and the written
-// values will be collected in a Value slice that will be put on a channel as
-// soon as the writer is closed.
-func makeValuesWriterAndCollect() (chan interface{}, <-chan []interface{}) {
-	chanValues := make(chan interface{}, outChanBufferSize)
-	chanCollected := make(chan []interface{})
-
-	go func() {
-		var collected []interface{}
-		for {
-			for v := range chanValues {
-				collected = append(collected, v)
-			}
-			chanCollected <- collected
-		}
-	}()
-
-	return chanValues, chanCollected
-}

+ 0 - 19
pkg/web/web_test.go

@@ -1,19 +0,0 @@
-package web
-
-import (
-	"testing"
-
-	. "src.elv.sh/pkg/prog/progtest"
-)
-
-func TestProgram(t *testing.T) {
-	Test(t, Program,
-		ThatElvish("-web", "x").
-			ExitsWith(2).
-			WritesStderrContaining("arguments are not allowed with -web"),
-
-		ThatElvish("-web", "-c").
-			ExitsWith(2).
-			WritesStderrContaining("-c cannot be used together with -web"),
-	)
-}