mirror of
https://github.com/tenox7/wrp.git
synced 2026-02-14 13:46:32 +00:00
Compare commits
14 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
76e72d5368 | ||
|
|
c4d9833707 | ||
|
|
9cd286add8 | ||
|
|
fdfbe80024 | ||
|
|
d602124ed6 | ||
|
|
6e5e829b02 | ||
|
|
f978d91ba9 | ||
|
|
9b15feacb2 | ||
|
|
08a89c6097 | ||
|
|
fa3bd3f8fb | ||
|
|
55f4e45b4c | ||
|
|
9e77aa7261 | ||
|
|
8a9870d8e2 | ||
|
|
7c33bc67dc |
10
Makefile
10
Makefile
@@ -1,21 +1,19 @@
|
||||
all: wrp
|
||||
|
||||
wrp: wrp.go statik
|
||||
wrp: wrp.go
|
||||
go build wrp.go
|
||||
|
||||
cross: statik
|
||||
cross:
|
||||
GOOS=linux GOARCH=amd64 go build -a -o wrp-amd64-linux wrp.go
|
||||
GOOS=freebsd GOARCH=amd64 go build -a -o wrp-amd64-freebsd wrp.go
|
||||
GOOS=openbsd GOARCH=amd64 go build -a -o wrp-amd64-openbsd wrp.go
|
||||
GOOS=darwin GOARCH=amd64 go build -a -o wrp-amd64-macos wrp.go
|
||||
GOOS=darwin GOARCH=arm64 go build -a -o wrp-arm64-macos wrp.go
|
||||
GOOS=windows GOARCH=amd64 go build -a -o wrp-amd64-windows.exe wrp.go
|
||||
GOOS=windows GOARCH=386 go build -a -o wrp-386-windows.exe wrp.go
|
||||
GOOS=linux GOARCH=arm go build -a -o wrp-arm-linux wrp.go
|
||||
GOOS=linux GOARCH=arm64 go build -a -o wrp-arm64-linux wrp.go
|
||||
|
||||
statik: wrp.html
|
||||
go generate
|
||||
|
||||
docker: wrp
|
||||
docker build -t tenox7/wrp:latest .
|
||||
|
||||
@@ -27,4 +25,4 @@ gcrio:
|
||||
docker push gcr.io/tenox7/wrp
|
||||
|
||||
clean:
|
||||
rm -rf wrp-* wrp statik
|
||||
rm -rf wrp-* wrp
|
||||
|
||||
7
go.mod
7
go.mod
@@ -4,9 +4,8 @@ go 1.16
|
||||
|
||||
require (
|
||||
github.com/MaxHalford/halfgone v0.0.0-20171017091812-482157b86ccb
|
||||
github.com/chromedp/cdproto v0.0.0-20210305224431-50b9f457e822
|
||||
github.com/chromedp/chromedp v0.6.8
|
||||
github.com/chromedp/cdproto v0.0.0-20221029224954-108014bf7279
|
||||
github.com/chromedp/chromedp v0.8.6
|
||||
github.com/ericpauley/go-quantize v0.0.0-20200331213906-ae555eb2afa4
|
||||
github.com/rakyll/statik v0.1.7
|
||||
golang.org/x/sys v0.0.0-20210305230114-8fe3ee5dd75b // indirect
|
||||
golang.org/x/sys v0.1.0 // indirect
|
||||
)
|
||||
|
||||
26
go.sum
26
go.sum
@@ -1,9 +1,10 @@
|
||||
github.com/MaxHalford/halfgone v0.0.0-20171017091812-482157b86ccb h1:YQ+d0g0P0F/06oDoeEgDHeZCIrnKgLxXcqYOpe8sTuU=
|
||||
github.com/MaxHalford/halfgone v0.0.0-20171017091812-482157b86ccb/go.mod h1:J86XzS1wgzJPjpQmpriJ+SetP17JSQUd9l+HWQK86jA=
|
||||
github.com/chromedp/cdproto v0.0.0-20210305224431-50b9f457e822 h1:iuUUtGk8vteAyrzYTdvn4gzVAw5Q7WEoDRinBQEiIe4=
|
||||
github.com/chromedp/cdproto v0.0.0-20210305224431-50b9f457e822/go.mod h1:At5TxYYdxkbQL0TSefRjhLE3Q0lgvqKKMSFUglJ7i1U=
|
||||
github.com/chromedp/chromedp v0.6.8 h1:hsMFAylK8PxqmpxzoxHkSJAV5qnixG0UJcNL70IRntg=
|
||||
github.com/chromedp/chromedp v0.6.8/go.mod h1:4NiJ4rKpkhU1Eor5stea0NvibADXd8drgtzj6+3eXZ4=
|
||||
github.com/chromedp/cdproto v0.0.0-20220924210414-0e3390be1777/go.mod h1:5Y4sD/eXpwrChIuxhSr/G20n9CdbCmoerOHnuAf0Zr0=
|
||||
github.com/chromedp/cdproto v0.0.0-20221029224954-108014bf7279 h1:7+D/pA8BoNzTpcM0Yw8issS95U/ipn0im5vzhfPzDZc=
|
||||
github.com/chromedp/cdproto v0.0.0-20221029224954-108014bf7279/go.mod h1:GKljq0VrfU4D5yc+2qA6OVr8pmO/MBbPEWqWQ/oqGEs=
|
||||
github.com/chromedp/chromedp v0.8.6 h1:KobeeqR2dpfKSG1prS3Y6+FbffMmGC6xmAobRXA9QEQ=
|
||||
github.com/chromedp/chromedp v0.8.6/go.mod h1:nBYHoD6YSNzrr82cIeuOzhw1Jo/s2o0QQ+ifTeoCZ+c=
|
||||
github.com/chromedp/sysutil v1.0.0 h1:+ZxhTpfpZlmchB58ih/LBHX52ky7w2VhQVKQMucy3Ic=
|
||||
github.com/chromedp/sysutil v1.0.0/go.mod h1:kgWmDdq8fTzXYcKIBqIYvRRTnYb9aNS9moAV0xufSww=
|
||||
github.com/ericpauley/go-quantize v0.0.0-20200331213906-ae555eb2afa4 h1:BBade+JlV/f7JstZ4pitd4tHhpN+w+6I+LyOS7B4fyU=
|
||||
@@ -12,14 +13,17 @@ github.com/gobwas/httphead v0.1.0 h1:exrUm0f4YX0L7EBwZHuCF4GDp8aJfVeBrlLQrs6NqWU
|
||||
github.com/gobwas/httphead v0.1.0/go.mod h1:O/RXo79gxV8G+RqlR/otEwx4Q36zl9rqC5u12GKvMCM=
|
||||
github.com/gobwas/pool v0.2.1 h1:xfeeEhW7pwmX8nuLVlqbzVc7udMDrwetjEv+TZIz1og=
|
||||
github.com/gobwas/pool v0.2.1/go.mod h1:q8bcK0KcYlCgd9e7WYLm9LpyS+YeLd8JVDW6WezmKEw=
|
||||
github.com/gobwas/ws v1.0.4 h1:5eXU1CZhpQdq5kXbKb+sECH5Ia5KiO6CYzIzdlVx6Bs=
|
||||
github.com/gobwas/ws v1.0.4/go.mod h1:szmBTxLgaFppYjEmNtny/v3w89xOydFnnZMcgRRu/EM=
|
||||
github.com/gobwas/ws v1.1.0 h1:7RFti/xnNkMJnrK7D1yQ/iCIB5OrrY/54/H930kIbHA=
|
||||
github.com/gobwas/ws v1.1.0/go.mod h1:nzvNcVha5eUziGrbxFCo6qFIojQHjJV5cLYIbezhfL0=
|
||||
github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY=
|
||||
github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
|
||||
github.com/ledongthuc/pdf v0.0.0-20220302134840-0c2507a12d80 h1:6Yzfa6GP0rIo/kULo2bwGEkFvCePZ3qHDDTC3/J9Swo=
|
||||
github.com/ledongthuc/pdf v0.0.0-20220302134840-0c2507a12d80/go.mod h1:imJHygn/1yfhB7XSJJKlFZKl/J+dCPAknuiaGOshXAs=
|
||||
github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0=
|
||||
github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
|
||||
github.com/rakyll/statik v0.1.7 h1:OF3QCZUuyPxuGEP7B4ypUa7sB/iHtqOTDYZXGM8KOdQ=
|
||||
github.com/rakyll/statik v0.1.7/go.mod h1:AlZONWzMtEnMs7W4e/1LURLiI49pIMmp6V9Unghqrcc=
|
||||
golang.org/x/sys v0.0.0-20210305215415-5cdee2b1b5a0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210305230114-8fe3ee5dd75b h1:ggRgirZABFolTmi3sn6Ivd9SipZwLedQ5wR0aAKnFxU=
|
||||
golang.org/x/sys v0.0.0-20210305230114-8fe3ee5dd75b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
github.com/orisano/pixelmatch v0.0.0-20220722002657-fb0b55479cde h1:x0TT0RDC7UhAVbbWWBzr41ElhJx5tXPWkIHA2HWPRuw=
|
||||
github.com/orisano/pixelmatch v0.0.0-20220722002657-fb0b55479cde/go.mod h1:nZgzbfBr3hhjoZnS66nKrHmduYNpc34ny7RK4z5/HM0=
|
||||
golang.org/x/sys v0.0.0-20201207223542-d4d67f95c62d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20220928140112-f11e5e49a4ec/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.1.0 h1:kunALQeHf1/185U1i0GOB/fy1IPRDDpuoOOqRReG57U=
|
||||
golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
|
||||
311
wrp.go
311
wrp.go
@@ -5,13 +5,12 @@
|
||||
// Copyright (c) 2019-2021 Google LLC
|
||||
//
|
||||
|
||||
//go:generate statik -f -src=. -include=wrp.html
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"embed"
|
||||
"flag"
|
||||
"fmt"
|
||||
"html/template"
|
||||
@@ -37,12 +36,10 @@ import (
|
||||
"github.com/chromedp/cdproto/page"
|
||||
"github.com/chromedp/chromedp"
|
||||
"github.com/ericpauley/go-quantize/quantize"
|
||||
"github.com/rakyll/statik/fs"
|
||||
_ "github.com/tenox7/wrp/statik"
|
||||
)
|
||||
|
||||
var (
|
||||
version = "4.5.2"
|
||||
version = "4.5.3"
|
||||
srv http.Server
|
||||
ctx context.Context
|
||||
cancel context.CancelFunc
|
||||
@@ -54,6 +51,9 @@ var (
|
||||
htmlTmpl *template.Template
|
||||
)
|
||||
|
||||
// go:embed *.html
|
||||
var fs embed.FS
|
||||
|
||||
type geom struct {
|
||||
w int64
|
||||
h int64
|
||||
@@ -101,55 +101,55 @@ type wrpReq struct {
|
||||
keys string // keys to send
|
||||
buttons string // Fn buttons
|
||||
imgType string // imgtype
|
||||
out http.ResponseWriter
|
||||
req *http.Request
|
||||
w http.ResponseWriter
|
||||
r *http.Request
|
||||
}
|
||||
|
||||
// Parse HTML Form, Process Input Boxes, Etc.
|
||||
func parseForm(w *wrpReq) {
|
||||
w.req.ParseForm()
|
||||
w.url = w.req.FormValue("url")
|
||||
if len(w.url) > 1 && !strings.HasPrefix(w.url, "http") {
|
||||
w.url = fmt.Sprintf("http://www.google.com/search?q=%s", url.QueryEscape(w.url))
|
||||
func (rq *wrpReq) parseForm() {
|
||||
rq.r.ParseForm()
|
||||
rq.url = rq.r.FormValue("url")
|
||||
if len(rq.url) > 1 && !strings.HasPrefix(rq.url, "http") {
|
||||
rq.url = fmt.Sprintf("http://www.google.com/search?q=%s", url.QueryEscape(rq.url))
|
||||
}
|
||||
w.width, _ = strconv.ParseInt(w.req.FormValue("w"), 10, 64)
|
||||
w.height, _ = strconv.ParseInt(w.req.FormValue("h"), 10, 64)
|
||||
if w.width < 10 && w.height < 10 {
|
||||
w.width = defGeom.w
|
||||
w.height = defGeom.h
|
||||
rq.width, _ = strconv.ParseInt(rq.r.FormValue("w"), 10, 64)
|
||||
rq.height, _ = strconv.ParseInt(rq.r.FormValue("h"), 10, 64)
|
||||
if rq.width < 10 && rq.height < 10 {
|
||||
rq.width = defGeom.w
|
||||
rq.height = defGeom.h
|
||||
}
|
||||
w.zoom, _ = strconv.ParseFloat(w.req.FormValue("z"), 64)
|
||||
if w.zoom < 0.1 {
|
||||
w.zoom = 1.0
|
||||
rq.zoom, _ = strconv.ParseFloat(rq.r.FormValue("z"), 64)
|
||||
if rq.zoom < 0.1 {
|
||||
rq.zoom = 1.0
|
||||
}
|
||||
w.colors, _ = strconv.ParseInt(w.req.FormValue("c"), 10, 64)
|
||||
if w.colors < 2 || w.colors > 256 {
|
||||
w.colors = defGeom.c
|
||||
rq.colors, _ = strconv.ParseInt(rq.r.FormValue("c"), 10, 64)
|
||||
if rq.colors < 2 || rq.colors > 256 {
|
||||
rq.colors = defGeom.c
|
||||
}
|
||||
w.keys = w.req.FormValue("k")
|
||||
w.buttons = w.req.FormValue("Fn")
|
||||
w.imgType = w.req.FormValue("t")
|
||||
if w.imgType != "gif" && w.imgType != "png" {
|
||||
w.imgType = defType
|
||||
rq.keys = rq.r.FormValue("k")
|
||||
rq.buttons = rq.r.FormValue("Fn")
|
||||
rq.imgType = rq.r.FormValue("t")
|
||||
if rq.imgType != "gif" && rq.imgType != "png" {
|
||||
rq.imgType = defType
|
||||
}
|
||||
log.Printf("%s WrpReq from UI Form: %+v\n", w.req.RemoteAddr, w)
|
||||
log.Printf("%s WrpReq from UI Form: %+v\n", rq.r.RemoteAddr, rq)
|
||||
}
|
||||
|
||||
// Display WP UI
|
||||
func printHTML(w wrpReq, p printParams) {
|
||||
w.out.Header().Set("Cache-Control", "max-age=0")
|
||||
w.out.Header().Set("Expires", "-1")
|
||||
w.out.Header().Set("Pragma", "no-cache")
|
||||
w.out.Header().Set("Content-Type", "text/html")
|
||||
func (rq *wrpReq) printHTML(p printParams) {
|
||||
rq.w.Header().Set("Cache-Control", "max-age=0")
|
||||
rq.w.Header().Set("Expires", "-1")
|
||||
rq.w.Header().Set("Pragma", "no-cache")
|
||||
rq.w.Header().Set("Content-Type", "text/html")
|
||||
data := uiData{
|
||||
Version: version,
|
||||
URL: w.url,
|
||||
URL: rq.url,
|
||||
BgColor: p.bgColor,
|
||||
Width: w.width,
|
||||
Height: w.height,
|
||||
NColors: w.colors,
|
||||
Zoom: w.zoom,
|
||||
ImgType: w.imgType,
|
||||
Width: rq.width,
|
||||
Height: rq.height,
|
||||
NColors: rq.colors,
|
||||
Zoom: rq.zoom,
|
||||
ImgType: rq.imgType,
|
||||
ImgSize: p.imgSize,
|
||||
ImgWidth: p.imgWidth,
|
||||
ImgHeight: p.imgHeight,
|
||||
@@ -157,23 +157,23 @@ func printHTML(w wrpReq, p printParams) {
|
||||
MapURL: p.mapURL,
|
||||
PageHeight: p.pageHeight,
|
||||
}
|
||||
err := htmlTmpl.Execute(w.out, data)
|
||||
err := htmlTmpl.Execute(rq.w, data)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
// Determine what action to take
|
||||
func action(w wrpReq) chromedp.Action {
|
||||
func (rq *wrpReq) action() chromedp.Action {
|
||||
// Mouse Click
|
||||
if w.mouseX > 0 && w.mouseY > 0 {
|
||||
log.Printf("%s Mouse Click %d,%d\n", w.req.RemoteAddr, w.mouseX, w.mouseY)
|
||||
return chromedp.MouseClickXY(float64(w.mouseX)/float64(w.zoom), float64(w.mouseY)/float64(w.zoom))
|
||||
if rq.mouseX > 0 && rq.mouseY > 0 {
|
||||
log.Printf("%s Mouse Click %d,%d\n", rq.r.RemoteAddr, rq.mouseX, rq.mouseY)
|
||||
return chromedp.MouseClickXY(float64(rq.mouseX)/float64(rq.zoom), float64(rq.mouseY)/float64(rq.zoom))
|
||||
}
|
||||
// Buttons
|
||||
if len(w.buttons) > 0 {
|
||||
log.Printf("%s Button %v\n", w.req.RemoteAddr, w.buttons)
|
||||
switch w.buttons {
|
||||
if len(rq.buttons) > 0 {
|
||||
log.Printf("%s Button %v\n", rq.r.RemoteAddr, rq.buttons)
|
||||
switch rq.buttons {
|
||||
case "Bk":
|
||||
return chromedp.NavigateBack()
|
||||
case "St":
|
||||
@@ -195,43 +195,59 @@ func action(w wrpReq) chromedp.Action {
|
||||
}
|
||||
}
|
||||
// Keys
|
||||
if len(w.keys) > 0 {
|
||||
log.Printf("%s Sending Keys: %#v\n", w.req.RemoteAddr, w.keys)
|
||||
return chromedp.KeyEvent(w.keys)
|
||||
if len(rq.keys) > 0 {
|
||||
log.Printf("%s Sending Keys: %#v\n", rq.r.RemoteAddr, rq.keys)
|
||||
return chromedp.KeyEvent(rq.keys)
|
||||
}
|
||||
// Navigate to URL
|
||||
log.Printf("%s Processing Capture Request for %s\n", w.req.RemoteAddr, w.url)
|
||||
return chromedp.Navigate(w.url)
|
||||
log.Printf("%s Processing Capture Request for %s\n", rq.r.RemoteAddr, rq.url)
|
||||
return chromedp.Navigate(rq.url)
|
||||
}
|
||||
|
||||
// Process Keyboard and Mouse events or Navigate to the desired URL.
|
||||
func navigate(w wrpReq) {
|
||||
err := chromedp.Run(ctx, action(w))
|
||||
func (rq *wrpReq) navigate() {
|
||||
err := chromedp.Run(ctx, rq.action())
|
||||
if err != nil {
|
||||
if err.Error() == "context canceled" {
|
||||
log.Printf("%s Contex cancelled, try again", w.req.RemoteAddr)
|
||||
fmt.Fprintf(w.out, "<BR>%s<BR> -- restarting, try again", err)
|
||||
log.Printf("%s Contex cancelled, try again", rq.r.RemoteAddr)
|
||||
fmt.Fprintf(rq.w, "<BR>%s<BR> -- restarting, try again", err)
|
||||
ctx, cancel = chromedp.NewContext(context.Background())
|
||||
return
|
||||
}
|
||||
log.Printf("%s %s", w.req.RemoteAddr, err)
|
||||
fmt.Fprintf(w.out, "<BR>%s<BR>", err)
|
||||
log.Printf("%s %s", rq.r.RemoteAddr, err)
|
||||
fmt.Fprintf(rq.w, "<BR>%s<BR>", err)
|
||||
}
|
||||
}
|
||||
|
||||
// https://github.com/chromedp/chromedp/issues/979
|
||||
func chromedpCaptureScreenshot(res *[]byte, h int64) chromedp.Action {
|
||||
if res == nil {
|
||||
panic("res cannot be nil")
|
||||
}
|
||||
if h == 0 {
|
||||
return chromedp.CaptureScreenshot(res)
|
||||
}
|
||||
|
||||
return chromedp.ActionFunc(func(ctx context.Context) error {
|
||||
var err error
|
||||
*res, err = page.CaptureScreenshot().Do(ctx)
|
||||
return err
|
||||
})
|
||||
}
|
||||
|
||||
// Capture currently rendered web page to an image and fake ISMAP
|
||||
func capture(w wrpReq) {
|
||||
func (rq *wrpReq) capture() {
|
||||
var err error
|
||||
var styles []*css.ComputedStyleProperty
|
||||
var r, g, b int
|
||||
var h int64
|
||||
var pngcap []byte
|
||||
chromedp.Run(ctx,
|
||||
emulation.SetDeviceMetricsOverride(int64(float64(w.width)/w.zoom), 10, w.zoom, false),
|
||||
chromedp.Location(&w.url),
|
||||
emulation.SetDeviceMetricsOverride(int64(float64(rq.width)/rq.zoom), 10, rq.zoom, false),
|
||||
chromedp.Location(&rq.url),
|
||||
chromedp.ComputedStyle("body", &styles, chromedp.ByQuery),
|
||||
chromedp.ActionFunc(func(ctx context.Context) error {
|
||||
_, _, s, err := page.GetLayoutMetrics().Do(ctx)
|
||||
_, _, _, _, _, s, err := page.GetLayoutMetrics().Do(ctx)
|
||||
if err == nil {
|
||||
h = int64(math.Ceil(s.Height))
|
||||
}
|
||||
@@ -243,58 +259,59 @@ func capture(w wrpReq) {
|
||||
fmt.Sscanf(style.Value, "rgb(%d,%d,%d)", &r, &g, &b)
|
||||
}
|
||||
}
|
||||
log.Printf("%s Landed on: %s, Height: %v\n", w.req.RemoteAddr, w.url, h)
|
||||
height := int64(float64(w.height) / w.zoom)
|
||||
if w.height == 0 && h > 0 {
|
||||
log.Printf("%s Landed on: %s, Height: %v\n", rq.r.RemoteAddr, rq.url, h)
|
||||
height := int64(float64(rq.height) / rq.zoom)
|
||||
if rq.height == 0 && h > 0 {
|
||||
height = h + 30
|
||||
}
|
||||
chromedp.Run(ctx, emulation.SetDeviceMetricsOverride(int64(float64(w.width)/w.zoom), height, w.zoom, false))
|
||||
// Capture screenshot...
|
||||
err = chromedp.Run(ctx,
|
||||
chromedp.Sleep(time.Second*2),
|
||||
chromedp.CaptureScreenshot(&pngcap),
|
||||
chromedp.Run(
|
||||
ctx, emulation.SetDeviceMetricsOverride(int64(float64(rq.width)/rq.zoom), height, rq.zoom, false),
|
||||
chromedp.Sleep(time.Second*2), // TODO(tenox): totally lame, find a better way to determine if page is rendered
|
||||
)
|
||||
// Capture screenshot...
|
||||
err = chromedp.Run(ctx, chromedpCaptureScreenshot(&pngcap, rq.height))
|
||||
if err != nil {
|
||||
if err.Error() == "context canceled" {
|
||||
log.Printf("%s Contex cancelled, try again", w.req.RemoteAddr)
|
||||
fmt.Fprintf(w.out, "<BR>%s<BR> -- restarting, try again", err)
|
||||
log.Printf("%s Contex cancelled, try again", rq.r.RemoteAddr)
|
||||
fmt.Fprintf(rq.w, "<BR>%s<BR> -- restarting, try again", err)
|
||||
ctx, cancel = chromedp.NewContext(context.Background())
|
||||
return
|
||||
}
|
||||
log.Printf("%s Failed to capture screenshot: %s\n", w.req.RemoteAddr, err)
|
||||
fmt.Fprintf(w.out, "<BR>Unable to capture screenshot:<BR>%s<BR>\n", err)
|
||||
log.Printf("%s Failed to capture screenshot: %s\n", rq.r.RemoteAddr, err)
|
||||
fmt.Fprintf(rq.w, "<BR>Unable to capture screenshot:<BR>%s<BR>\n", err)
|
||||
return
|
||||
}
|
||||
seq := rand.Intn(9999)
|
||||
imgpath := fmt.Sprintf("/img/%04d.%s", seq, w.imgType)
|
||||
imgpath := fmt.Sprintf("/img/%04d.%s", seq, rq.imgType)
|
||||
mappath := fmt.Sprintf("/map/%04d.map", seq)
|
||||
ismap[mappath] = w
|
||||
ismap[mappath] = *rq
|
||||
var ssize string
|
||||
var iw, ih int
|
||||
switch w.imgType {
|
||||
switch rq.imgType {
|
||||
case "gif":
|
||||
i, err := png.Decode(bytes.NewReader(pngcap))
|
||||
if err != nil {
|
||||
log.Printf("%s Failed to decode screenshot: %s\n", w.req.RemoteAddr, err)
|
||||
fmt.Fprintf(w.out, "<BR>Unable to decode page screenshot:<BR>%s<BR>\n", err)
|
||||
log.Printf("%s Failed to decode screenshot: %s\n", rq.r.RemoteAddr, err)
|
||||
fmt.Fprintf(rq.w, "<BR>Unable to decode page screenshot:<BR>%s<BR>\n", err)
|
||||
return
|
||||
}
|
||||
if w.colors == 2 {
|
||||
if rq.colors == 2 {
|
||||
gray := halfgone.ImageToGray(i)
|
||||
i = halfgone.FloydSteinbergDitherer{}.Apply(gray)
|
||||
}
|
||||
var gifbuf bytes.Buffer
|
||||
err = gif.Encode(&gifbuf, i, &gif.Options{NumColors: int(w.colors), Quantizer: quantize.MedianCutQuantizer{}})
|
||||
st := time.Now()
|
||||
err = gif.Encode(&gifbuf, i, &gif.Options{NumColors: int(rq.colors), Quantizer: quantize.MedianCutQuantizer{}})
|
||||
if err != nil {
|
||||
log.Printf("%s Failed to encode GIF: %s\n", w.req.RemoteAddr, err)
|
||||
fmt.Fprintf(w.out, "<BR>Unable to encode GIF:<BR>%s<BR>\n", err)
|
||||
log.Printf("%s Failed to encode GIF: %s\n", rq.r.RemoteAddr, err)
|
||||
fmt.Fprintf(rq.w, "<BR>Unable to encode GIF:<BR>%s<BR>\n", err)
|
||||
return
|
||||
}
|
||||
img[imgpath] = gifbuf
|
||||
ssize = fmt.Sprintf("%.0f KB", float32(len(gifbuf.Bytes()))/1024.0)
|
||||
iw = i.Bounds().Max.X
|
||||
ih = i.Bounds().Max.Y
|
||||
log.Printf("%s Encoded GIF image: %s, Size: %s, Colors: %d, %dx%d\n", w.req.RemoteAddr, imgpath, ssize, w.colors, iw, ih)
|
||||
log.Printf("%s Encoded GIF image: %s, Size: %s, Colors: %d, %dx%d, Time: %vms\n", rq.r.RemoteAddr, imgpath, ssize, rq.colors, iw, ih, time.Since(st).Milliseconds())
|
||||
case "png":
|
||||
pngbuf := bytes.NewBuffer(pngcap)
|
||||
img[imgpath] = *pngbuf
|
||||
@@ -302,9 +319,9 @@ func capture(w wrpReq) {
|
||||
ssize = fmt.Sprintf("%.0f KB", float32(len(pngbuf.Bytes()))/1024.0)
|
||||
iw = cfg.Width
|
||||
ih = cfg.Height
|
||||
log.Printf("%s Got PNG image: %s, Size: %s, %dx%d\n", w.req.RemoteAddr, imgpath, ssize, iw, ih)
|
||||
log.Printf("%s Got PNG image: %s, Size: %s, %dx%d\n", rq.r.RemoteAddr, imgpath, ssize, iw, ih)
|
||||
}
|
||||
printHTML(w, printParams{
|
||||
rq.printHTML(printParams{
|
||||
bgColor: fmt.Sprintf("#%02X%02X%02X", r, g, b),
|
||||
pageHeight: fmt.Sprintf("%d PX", h),
|
||||
imgSize: ssize,
|
||||
@@ -313,88 +330,89 @@ func capture(w wrpReq) {
|
||||
imgWidth: iw,
|
||||
imgHeight: ih,
|
||||
})
|
||||
log.Printf("%s Done with capture for %s\n", w.req.RemoteAddr, w.url)
|
||||
log.Printf("%s Done with capture for %s\n", rq.r.RemoteAddr, rq.url)
|
||||
}
|
||||
|
||||
// Process HTTP requests to WRP '/' url
|
||||
func pageServer(out http.ResponseWriter, req *http.Request) {
|
||||
log.Printf("%s Page Request for %s [%+v]\n", req.RemoteAddr, req.URL.Path, req.URL.RawQuery)
|
||||
var w wrpReq
|
||||
w.req = req
|
||||
w.out = out
|
||||
parseForm(&w)
|
||||
if len(w.url) < 4 {
|
||||
printHTML(w, printParams{bgColor: "#FFFFFF"})
|
||||
func pageServer(w http.ResponseWriter, r *http.Request) {
|
||||
log.Printf("%s Page Request for %s [%+v]\n", r.RemoteAddr, r.URL.Path, r.URL.RawQuery)
|
||||
rq := wrpReq{
|
||||
r: r,
|
||||
w: w,
|
||||
}
|
||||
rq.parseForm()
|
||||
if len(rq.url) < 4 {
|
||||
rq.printHTML(printParams{bgColor: "#FFFFFF"})
|
||||
return
|
||||
}
|
||||
navigate(w)
|
||||
capture(w)
|
||||
rq.navigate()
|
||||
rq.capture()
|
||||
}
|
||||
|
||||
// Process HTTP requests to ISMAP '/map/' url
|
||||
func mapServer(out http.ResponseWriter, req *http.Request) {
|
||||
log.Printf("%s ISMAP Request for %s [%+v]\n", req.RemoteAddr, req.URL.Path, req.URL.RawQuery)
|
||||
w, ok := ismap[req.URL.Path]
|
||||
w.req = req
|
||||
w.out = out
|
||||
func mapServer(w http.ResponseWriter, r *http.Request) {
|
||||
log.Printf("%s ISMAP Request for %s [%+v]\n", r.RemoteAddr, r.URL.Path, r.URL.RawQuery)
|
||||
rq, ok := ismap[r.URL.Path]
|
||||
rq.r = r
|
||||
rq.w = w
|
||||
if !ok {
|
||||
fmt.Fprintf(out, "Unable to find map %s\n", req.URL.Path)
|
||||
log.Printf("Unable to find map %s\n", req.URL.Path)
|
||||
fmt.Fprintf(w, "Unable to find map %s\n", r.URL.Path)
|
||||
log.Printf("Unable to find map %s\n", r.URL.Path)
|
||||
return
|
||||
}
|
||||
if !noDel {
|
||||
defer delete(ismap, req.URL.Path)
|
||||
defer delete(ismap, r.URL.Path)
|
||||
}
|
||||
n, err := fmt.Sscanf(req.URL.RawQuery, "%d,%d", &w.mouseX, &w.mouseY)
|
||||
n, err := fmt.Sscanf(r.URL.RawQuery, "%d,%d", &rq.mouseX, &rq.mouseY)
|
||||
if err != nil || n != 2 {
|
||||
fmt.Fprintf(out, "n=%d, err=%s\n", n, err)
|
||||
log.Printf("%s ISMAP n=%d, err=%s\n", req.RemoteAddr, n, err)
|
||||
fmt.Fprintf(w, "n=%d, err=%s\n", n, err)
|
||||
log.Printf("%s ISMAP n=%d, err=%s\n", r.RemoteAddr, n, err)
|
||||
return
|
||||
}
|
||||
log.Printf("%s WrpReq from ISMAP: %+v\n", req.RemoteAddr, w)
|
||||
if len(w.url) < 4 {
|
||||
printHTML(w, printParams{bgColor: "#FFFFFF"})
|
||||
log.Printf("%s WrpReq from ISMAP: %+v\n", r.RemoteAddr, rq)
|
||||
if len(rq.url) < 4 {
|
||||
rq.printHTML(printParams{bgColor: "#FFFFFF"})
|
||||
return
|
||||
}
|
||||
navigate(w)
|
||||
capture(w)
|
||||
rq.navigate()
|
||||
rq.capture()
|
||||
}
|
||||
|
||||
// Process HTTP requests for images '/img/' url
|
||||
func imgServer(out http.ResponseWriter, req *http.Request) {
|
||||
log.Printf("%s IMG Request for %s\n", req.RemoteAddr, req.URL.Path)
|
||||
imgbuf, ok := img[req.URL.Path]
|
||||
func imgServer(w http.ResponseWriter, r *http.Request) {
|
||||
log.Printf("%s IMG Request for %s\n", r.RemoteAddr, r.URL.Path)
|
||||
imgbuf, ok := img[r.URL.Path]
|
||||
if !ok || imgbuf.Bytes() == nil {
|
||||
fmt.Fprintf(out, "Unable to find image %s\n", req.URL.Path)
|
||||
log.Printf("%s Unable to find image %s\n", req.RemoteAddr, req.URL.Path)
|
||||
fmt.Fprintf(w, "Unable to find image %s\n", r.URL.Path)
|
||||
log.Printf("%s Unable to find image %s\n", r.RemoteAddr, r.URL.Path)
|
||||
return
|
||||
}
|
||||
if !noDel {
|
||||
defer delete(img, req.URL.Path)
|
||||
defer delete(img, r.URL.Path)
|
||||
}
|
||||
switch {
|
||||
case strings.HasPrefix(req.URL.Path, ".gif"):
|
||||
out.Header().Set("Content-Type", "image/gif")
|
||||
case strings.HasPrefix(req.URL.Path, ".png"):
|
||||
out.Header().Set("Content-Type", "image/png")
|
||||
case strings.HasPrefix(r.URL.Path, ".gif"):
|
||||
w.Header().Set("Content-Type", "image/gif")
|
||||
case strings.HasPrefix(r.URL.Path, ".png"):
|
||||
w.Header().Set("Content-Type", "image/png")
|
||||
}
|
||||
out.Header().Set("Content-Length", strconv.Itoa(len(imgbuf.Bytes())))
|
||||
out.Header().Set("Cache-Control", "max-age=0")
|
||||
out.Header().Set("Expires", "-1")
|
||||
out.Header().Set("Pragma", "no-cache")
|
||||
out.Write(imgbuf.Bytes())
|
||||
out.(http.Flusher).Flush()
|
||||
w.Header().Set("Content-Length", strconv.Itoa(len(imgbuf.Bytes())))
|
||||
w.Header().Set("Cache-Control", "max-age=0")
|
||||
w.Header().Set("Expires", "-1")
|
||||
w.Header().Set("Pragma", "no-cache")
|
||||
w.Write(imgbuf.Bytes())
|
||||
w.(http.Flusher).Flush()
|
||||
}
|
||||
|
||||
// Process HTTP requests for Shutdown via '/shutdown/' url
|
||||
func haltServer(out http.ResponseWriter, req *http.Request) {
|
||||
log.Printf("%s Shutdown Request for %s\n", req.RemoteAddr, req.URL.Path)
|
||||
out.Header().Set("Cache-Control", "max-age=0")
|
||||
out.Header().Set("Expires", "-1")
|
||||
out.Header().Set("Pragma", "no-cache")
|
||||
out.Header().Set("Content-Type", "text/plain")
|
||||
fmt.Fprintf(out, "Shutting down WRP...\n")
|
||||
out.(http.Flusher).Flush()
|
||||
func haltServer(w http.ResponseWriter, r *http.Request) {
|
||||
log.Printf("%s Shutdown Request for %s\n", r.RemoteAddr, r.URL.Path)
|
||||
w.Header().Set("Cache-Control", "max-age=0")
|
||||
w.Header().Set("Expires", "-1")
|
||||
w.Header().Set("Pragma", "no-cache")
|
||||
w.Header().Set("Content-Type", "text/plain")
|
||||
fmt.Fprintf(w, "Shutting down WRP...\n")
|
||||
w.(http.Flusher).Flush()
|
||||
time.Sleep(time.Second * 2)
|
||||
cancel()
|
||||
srv.Shutdown(context.Background())
|
||||
@@ -406,21 +424,17 @@ func tmpl(t string) string {
|
||||
var tmpl []byte
|
||||
fh, err := os.Open(t)
|
||||
if err != nil {
|
||||
goto statik
|
||||
goto builtin
|
||||
}
|
||||
tmpl, err = ioutil.ReadAll(fh)
|
||||
if err != nil {
|
||||
goto statik
|
||||
goto builtin
|
||||
}
|
||||
log.Printf("Got UI template from %v file\n", t)
|
||||
return string(tmpl)
|
||||
|
||||
statik:
|
||||
sfs, err := fs.New()
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
fhs, err := sfs.Open("/wrp.html")
|
||||
builtin:
|
||||
fhs, err := fs.Open("/wrp.html")
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
@@ -461,9 +475,10 @@ func main() {
|
||||
)
|
||||
actx, acancel := chromedp.NewExecAllocator(context.Background(), opts...)
|
||||
defer acancel()
|
||||
if debug {
|
||||
switch debug {
|
||||
case true:
|
||||
ctx, cancel = chromedp.NewContext(actx, chromedp.WithDebugf(log.Printf))
|
||||
} else {
|
||||
default:
|
||||
ctx, cancel = chromedp.NewContext(actx)
|
||||
}
|
||||
defer cancel()
|
||||
|
||||
8
wrp.html
8
wrp.html
@@ -25,11 +25,11 @@
|
||||
<OPTION VALUE="png" {{ if eq .ImgType "png"}}SELECTED{{end}}>PNG</OPTION>
|
||||
</SELECT>
|
||||
C <SELECT NAME="c">
|
||||
<OPTION VALUE="2" {{ if eq .NColors 2}}SELECTED{{end}}>2</OPTION>
|
||||
<OPTION VALUE="16" {{ if eq .NColors 16}}SELECTED{{end}}>16</OPTION>
|
||||
<OPTION VALUE="64" {{ if eq .NColors 64}}SELECTED{{end}}>64</OPTION>
|
||||
<OPTION VALUE="128" {{ if eq .NColors 128}}SELECTED{{end}}>128</OPTION>
|
||||
<OPTION VALUE="256" {{ if eq .NColors 256}}SELECTED{{end}}>256</OPTION>
|
||||
<OPTION VALUE="128" {{ if eq .NColors 128}}SELECTED{{end}}>128</OPTION>
|
||||
<OPTION VALUE="64" {{ if eq .NColors 64}}SELECTED{{end}}>64</OPTION>
|
||||
<OPTION VALUE="16" {{ if eq .NColors 16}}SELECTED{{end}}>16</OPTION>
|
||||
<OPTION VALUE="2" {{ if eq .NColors 2}}SELECTED{{end}}>2</OPTION>
|
||||
</SELECT>
|
||||
K <INPUT TYPE="TEXT" NAME="k" VALUE="" SIZE="4">
|
||||
<INPUT TYPE="SUBMIT" NAME="Fn" VALUE="Bs">
|
||||
|
||||
Reference in New Issue
Block a user