Compare commits

...

23 Commits

Author SHA1 Message Date
mappu 24cef16b4e doc/README: add archive download links 2020-05-06 18:14:20 +12:00
mappu a147d03839 doc: track image screenshots 2020-05-06 18:14:09 +12:00
mappu 70e17a48ba doc: remove TODO (moved to Gitea issues) 2018-12-31 18:17:51 +13:00
mappu d730fe65f6 doc: top-level README 2018-12-31 18:13:06 +13:00
mappu 63b573fd57 convert to Go Modules 2018-12-31 18:10:46 +13:00
mappu 304baa8020 hg2git: convert ignores/tags files 2018-12-31 18:10:22 +13:00
mappu 0fe8dc8f1b doc: add some screenshots 2017-04-23 17:33:03 +12:00
mappu 570cffe84e doc: add go-get tags 2017-04-23 17:09:35 +12:00
mappu 5802def7bc doc: update readme 2017-04-23 16:58:39 +12:00
mappu 5e6010bede bump all versions to 1.0.2 2017-03-27 21:53:01 +13:00
mappu 21829f0c1f Added tag release-1.0.1 for changeset 31148bbc099a 2017-03-27 21:52:47 +13:00
mappu 7e4a90920d readme 2017-03-27 21:49:41 +13:00
mappu 7951e09238 fixes for 5aad4b6dc90e 2017-03-27 21:49:05 +13:00
mappu eab781794e fix zero-value for maxhistorylines actually meaning zero history lines 2017-03-27 20:35:54 +13:00
mappu f7c70603f2 doc: update TODO 2017-03-27 20:16:32 +13:00
mappu b7ebd321d0 tasks: nicer time format, display more accurate time format on hover 2017-03-27 20:16:22 +13:00
mappu ef252d5cab tasks: always display list in sorted order (oldest first) 2017-03-27 20:16:12 +13:00
mappu 0768e10403 remove title on text elements (fixes long-press on Fennec) 2017-03-27 20:04:53 +13:00
mappu 820805b063 set default viewport for mobile 2017-03-27 20:04:15 +13:00
mappu 194c0b0405 allow unmarshalling consts as strings 2017-03-27 20:03:19 +13:00
mappu e7689eabad bump versions to 1.0.1 2017-03-25 17:09:05 +13:00
mappu 0e22171779 doc: update TODO 2017-03-25 16:53:26 +13:00
mappu d47dea6933 Added tag release-1.0.0 for changeset b851907a3b9a 2017-03-25 16:29:32 +13:00
18 changed files with 131 additions and 38 deletions

5
.gitignore vendored Normal file
View File

@ -0,0 +1,5 @@
cmd/webcmd/webcmd
cmd/webcmd/webcmd.exe
cmd/webcmd/webcmd.conf
_dist/*

View File

@ -1,6 +0,0 @@
mode:regex
^webcmd\.
^cmd/webcmd/webcmd$
^cmd/webcmd/webcmd.conf$
^_dist/.+\.(?:zip|tar\.xz)$

View File

@ -1,6 +1,6 @@
.PHONY: all clean
VERSION := 1.0.0
VERSION := 1.0.2
OBJS := webcmd-$(VERSION)-linux64.tar.xz \
webcmd-$(VERSION)-linux32.tar.xz \

42
README.md Normal file
View File

@ -0,0 +1,42 @@
# webcmd
A web-based interface for arbitrary command-line tools.
Configure the possible options for your command (e.g. optional flags, custom arguments) and then remotely invoke the tool via a web interface. The web interface displays stdout/stderr of recent and in-progress tasks, and can cancel a long-running command at any time.
## Usage
```
Usage of ./webcmd:
-config string
Path to configuration file (default "webcmd.conf")
-version
Display version number and exit
```
## Configuration
See the included `webcmd.conf-sample` file for an example configuration implementing a Looking Glass server over the top of `/bin/ping`.
## Changelog
2017-03-27 1.0.1
- Enhancement: Simplify configuration file format, allow parsing const strings directly
- Enhancement: Improve time format display
- Fix an issue with pasting into form fields on Firefox Mobile
- Fix an issue with not consistently interpreting `MaxHistoryLines:0` as infinite history
- Fix a cosmetic issue with mobile viewports
- Fix a cosmetic issue with task ordering
- [⬇️ webcmd-win64-1.0.1.zip](https://git.ivysaur.me/attachments/627d5246-0f51-4546-99b1-61d9b9b0cc0b) *(1.46 MiB)*
- [⬇️ webcmd-win32-1.0.1.zip](https://git.ivysaur.me/attachments/92de57b3-6f5c-4ba4-ac43-9f85c89041dd) *(1.38 MiB)*
- [⬇️ webcmd-src-1.0.1.zip](https://git.ivysaur.me/attachments/120a0a7c-52ab-4bb9-94fe-40d269b0669d) *(11.51 KiB)*
- [⬇️ webcmd-linux64-1.0.1.tar.xz](https://git.ivysaur.me/attachments/41d001ed-11b7-499c-ba18-1a22fe0ed140) *(1.14 MiB)*
- [⬇️ webcmd-linux32-1.0.1.tar.xz](https://git.ivysaur.me/attachments/0cb47392-36d1-4f48-9ee6-271f06dba952) *(1.06 MiB)*
2017-03-25 1.0.0
- Initial public release
- [⬇️ webcmd-win64-1.0.0.zip](https://git.ivysaur.me/attachments/6442cde4-0dfe-432d-9cb3-42272c8e6551) *(1.46 MiB)*
- [⬇️ webcmd-win32-1.0.0.zip](https://git.ivysaur.me/attachments/261489d4-8393-450c-9f72-1bca009e0942) *(1.37 MiB)*
- [⬇️ webcmd-src-1.0.0.zip](https://git.ivysaur.me/attachments/cbac2a73-2af0-4c60-ab0a-9970250c9a6e) *(10.50 KiB)*
- [⬇️ webcmd-linux64-1.0.0.tar.xz](https://git.ivysaur.me/attachments/a713a0f5-e3de-442c-a090-26ae49b03ac9) *(1.14 MiB)*
- [⬇️ webcmd-linux32-1.0.0.tar.xz](https://git.ivysaur.me/attachments/86d5e65e-c3da-4741-a0c0-f4ec2e123689) *(1.06 MiB)*

View File

@ -87,7 +87,7 @@ func (this *App) LaunchTask(workDir string, params []string) (taskRef string, er
task := this.tasks[ref]
task.output = append(task.output, OutputLine{isError: isError, text: text})
if len(task.output) > 2*this.cfg.MaxHistoryLines {
if this.cfg.MaxHistoryLines > 0 && len(task.output) > 2*this.cfg.MaxHistoryLines {
task.output = task.output[this.cfg.MaxHistoryLines:]
}
this.tasks[ref] = task

View File

@ -1,20 +0,0 @@
A web-based interface for arbitrary command-line tools.
Configure the possible options for your command (e.g. optional flags, custom arguments) and remotely invoke the tool via a web interface. The web interface displays stdout/stderr of recent tasks.
=USAGE=
`Usage of ./webcmd:
-config string
Path to configuration file (default "webcmd.conf")
-version
Display version number and exit`
=CONFIGURATION=
See the included `webcmd.conf-sample` file for an example configuration implementing a Looking Glass server over the top of `/bin/ping`.
=CHANGELOG=
2017-03-25 1.0.0
- Initial public release

BIN
_dist/image1.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

BIN
_dist/image2.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 38 KiB

BIN
_dist/image3.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 61 KiB

View File

@ -10,10 +10,10 @@
{
"Title": "Ping",
"Execution": [
{"ParamType": 0, "Value": "/bin/ping"},
{"ParamType": 0, "Value": "-c"},
{"ParamType": 0, "Value": "4"},
{"ParamType": 0, "Value": "--"},
"/bin/ping",
"-c",
"4",
"--",
{"ParamType": 1, "Value": "example.com", "Description": "Target host"}
]
}

View File

@ -1,5 +1,10 @@
package webcmd
import (
"encoding/json"
"errors"
)
type ParamType int
const (
@ -16,15 +21,47 @@ const (
)
type InputParam struct {
Description string `json:",omitempty"` // only use for editable parameters
Description string `json:",omitempty"` // only used for editable parameters
ParamType ParamType
Value string
}
func (ip *InputParam) UnmarshalJSON(b []byte) error {
switch b[0] {
case '"':
ip.Description = ""
ip.ParamType = PARAMTYPE_CONST
tmp := ""
err := json.Unmarshal(b, &tmp)
if err != nil {
return err
}
ip.Value = tmp
case '{':
read := struct {
Description string `json:",omitempty"`
ParamType ParamType
Value string
}{}
err := json.Unmarshal(b, &read)
if err != nil {
return err
}
*ip = read
return nil
default:
return errors.New("Malformed InputParam")
}
return nil
}
type CommandConfig struct {
Title string
WorkingDir string // default empty-string: getcwd()
Execution []InputParam // TODO allow plain strings as a shorthand for PARAMTYPE_CONST
Execution []InputParam // Can be unmarshalled using plain strings
}
type AppConfig struct {

BIN
doc/image1.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

BIN
doc/image2.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 38 KiB

BIN
doc/image3.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 61 KiB

1
go.mod Normal file
View File

@ -0,0 +1 @@
module code.ivysaur.me/webcmd

View File

@ -23,8 +23,8 @@ func (this *App) Serve_Homepage(w http.ResponseWriter) {
case PARAMTYPE_CONST:
// not configurable parameter
case PARAMTYPE_STRING:
fmt.Fprintf(w, `<input type="text" name="param[%d]" placeholder="%s" title="%s" value="%s"><br>`,
i, hesc(param.Description), hesc(param.Description), hesc(param.Value))
fmt.Fprintf(w, `<input type="text" name="param[%d]" placeholder="%s" value="%s"><br>`,
i, hesc(param.Description), hesc(param.Value))
case PARAMTYPE_OPTIONAL:
fmt.Fprintf(w, `<input type="hidden" name="param[%d]" value="off"><label><input type="checkbox" name="param[%d]" value="on">%s</label><br>`,
i, i, hesc(param.Description))

View File

@ -3,9 +3,29 @@ package webcmd
import (
"fmt"
"net/http"
"sort"
"time"
)
type TaskListItem struct {
ref string
start int64
}
type TaskList []TaskListItem
func (tl TaskList) Len() int {
return len(tl)
}
func (tl TaskList) Swap(i, j int) {
tl[i], tl[j] = tl[j], tl[i]
}
func (tl TaskList) Less(i, j int) bool {
return tl[i].start < tl[j].start
}
func (this *App) Serve_Tasks(w http.ResponseWriter) {
w.Header().Set("Content-Type", "text/html;charset=UTF-8")
@ -26,15 +46,28 @@ func (this *App) Serve_Tasks(w http.ResponseWriter) {
this.tasksMtx.RLock()
defer this.tasksMtx.RUnlock()
tl := make(TaskList, 0, len(this.tasks))
for ref, t := range this.tasks {
tl = append(tl, TaskListItem{ref, t.started})
}
sort.Sort(tl)
for _, tlRef := range tl {
ref := tlRef.ref
t := this.tasks[ref]
startTime := time.Unix(t.started, 0)
fmt.Fprintf(w,
`<tr>
<td><a href="/task/%s">%s</td>
<td>%s</td>
<td><span title="%s">%s</span></td>
<td>
`,
hesc(ref), hesc(ref),
hesc(time.Unix(t.started, 0).Format(time.RFC822Z)),
hesc(startTime.Format(time.RFC3339)),
hesc(startTime.Format(time.RFC822)),
)
if t.Finished() {

View File

@ -13,6 +13,7 @@ func (this *App) ServePartial_Header(w http.ResponseWriter, slug string) {
<meta charset="UTF-8">
<title>`+hesc(this.cfg.AppTitle)+`</title>
<link rel="stylesheet" type="text/css" href="/style.css">
<meta viewport="width=device-width, initial-scale=1">
</head>
<body>
<h2>`+hesc(this.cfg.AppTitle)+`</h2>