aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--go.mod14
-rw-r--r--go.sum28
-rw-r--r--plugins/base/public/message.html9
-rw-r--r--plugins/base/routes.go48
-rw-r--r--plugins/base/strconv.go12
-rw-r--r--themes/sourcehut/message.html9
6 files changed, 81 insertions, 39 deletions
diff --git a/go.mod b/go.mod
index 02a79d7..3deedc8 100644
--- a/go.mod
+++ b/go.mod
@@ -5,8 +5,9 @@ go 1.13
require (
github.com/aymerick/douceur v0.2.0
github.com/chris-ramon/douceur v0.2.0
- github.com/emersion/go-ical v0.0.0-20200225182515-5cc64a0054ad // indirect
- github.com/emersion/go-imap v1.0.3
+ github.com/dgrijalva/jwt-go v3.2.0+incompatible // indirect
+ github.com/emersion/go-ical v0.0.0-20200225233454-26ef720b8bf1 // indirect
+ github.com/emersion/go-imap v1.0.4
github.com/emersion/go-imap-metadata v0.0.0-20200128185110-9d939d2a0915
github.com/emersion/go-imap-move v0.0.0-20190710073258-6e5a51a5b342
github.com/emersion/go-imap-specialuse v0.0.0-20161227184202-ba031ced6a62
@@ -17,14 +18,13 @@ require (
github.com/emersion/go-webdav v0.2.1-0.20200227113614-abadf534f49a
github.com/google/uuid v1.1.1
github.com/gorilla/css v1.0.0 // indirect
- github.com/labstack/echo/v4 v4.1.15-0.20200203180927-504f39abaf32
+ github.com/labstack/echo/v4 v4.1.15
github.com/labstack/gommon v0.3.0
- github.com/mattn/go-isatty v0.0.12 // indirect
github.com/microcosm-cc/bluemonday v1.0.2
github.com/yuin/gopher-lua v0.0.0-20191220021717-ab39c6098bdb
gitlab.com/golang-commonmark/linkify v0.0.0-20200225224916-64bca66f6ad3
- golang.org/x/crypto v0.0.0-20200221231518-2aa609cf4a9d // indirect
- golang.org/x/net v0.0.0-20200225223329-5d076fcf07a8
- golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae // indirect
+ golang.org/x/crypto v0.0.0-20200317142112-1b76d66859c6 // indirect
+ golang.org/x/net v0.0.0-20200301022130-244492dfa37a
+ golang.org/x/sys v0.0.0-20200317113312-5766fd39f98d // indirect
layeh.com/gopher-luar v1.0.7
)
diff --git a/go.sum b/go.sum
index e7716fd..9e5a30e 100644
--- a/go.sum
+++ b/go.sum
@@ -12,10 +12,12 @@ github.com/dgrijalva/jwt-go v3.2.0+incompatible h1:7qlOGliEKZXTDg6OTjfoBKDXWrumC
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
github.com/emersion/go-ical v0.0.0-20200224201310-cd514449c39e h1:YGM1sI7edZOt8KAfX9Miq/X99d2QXdgjkJ7vN4HjxAA=
github.com/emersion/go-ical v0.0.0-20200224201310-cd514449c39e/go.mod h1:4xVTBPcT43a1pp3vdaa+FuRdX5XhKCZPpWv7m0z9ByM=
-github.com/emersion/go-ical v0.0.0-20200225182515-5cc64a0054ad h1:OKhKFSWeuAbVzgBsas+QCjCFLzi7pRX/FEhDudYHiQw=
-github.com/emersion/go-ical v0.0.0-20200225182515-5cc64a0054ad/go.mod h1:4xVTBPcT43a1pp3vdaa+FuRdX5XhKCZPpWv7m0z9ByM=
+github.com/emersion/go-ical v0.0.0-20200225233454-26ef720b8bf1 h1:v0W797seT60q3pzrphQUKh22Nt8uS7rgZyD6lqYgM0E=
+github.com/emersion/go-ical v0.0.0-20200225233454-26ef720b8bf1/go.mod h1:4xVTBPcT43a1pp3vdaa+FuRdX5XhKCZPpWv7m0z9ByM=
github.com/emersion/go-imap v1.0.3 h1:5eEee8/DTSIPfliiWqwfvjPGkU8bBtvOy/Wx+eeXzO4=
github.com/emersion/go-imap v1.0.3/go.mod h1:yKASt+C3ZiDAiCSssxg9caIckWF/JG7ZQTO7GAmvicU=
+github.com/emersion/go-imap v1.0.4 h1:uiCAIHM6Z5Jwkma1zdNDWWXxSCqb+/xHBkHflD7XBro=
+github.com/emersion/go-imap v1.0.4/go.mod h1:yKASt+C3ZiDAiCSssxg9caIckWF/JG7ZQTO7GAmvicU=
github.com/emersion/go-imap-metadata v0.0.0-20200128185110-9d939d2a0915 h1:8xzODjLqrfAJo+CNhX0Fp47vdVN0ZvmGV3CPt/Ex1nU=
github.com/emersion/go-imap-metadata v0.0.0-20200128185110-9d939d2a0915/go.mod h1:6mXMzbK9Ts0mrrBibqy56SqZpuFMry5AedTgu6qY5zM=
github.com/emersion/go-imap-move v0.0.0-20190710073258-6e5a51a5b342 h1:5p1t3e1PomYgLWwEwhwEU5kVBwcyAcVrOpexv8AeZx0=
@@ -39,18 +41,17 @@ github.com/google/uuid v1.1.1 h1:Gkbcsh/GbpXz7lPftLA3P6TYMwjCLYm83jiFQZF/3gY=
github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/gorilla/css v1.0.0 h1:BQqNyPTi50JCFMTw/b67hByjMVXZRwGha6wxVGkeihY=
github.com/gorilla/css v1.0.0/go.mod h1:Dn721qIggHpt4+EFCcTLTU/vk5ySda2ReITrtgBl60c=
-github.com/labstack/echo/v4 v4.1.15-0.20200203180927-504f39abaf32 h1:UiIEDYxPPmjl6mMIY4QPDguD/QAtK+gR4IRMSrjWmeA=
-github.com/labstack/echo/v4 v4.1.15-0.20200203180927-504f39abaf32/go.mod h1:mbsytw7LXzfWxMLdvzjjeERCwTL3PI03GIPpUpaMnfQ=
+github.com/labstack/echo/v4 v4.1.15 h1:4aE6KfJC+wCnMjODwcpeEGWGsRfszxZMwB3QVTECj2I=
+github.com/labstack/echo/v4 v4.1.15/go.mod h1:GWO5IBVzI371K8XJe50CSvHjQCafK6cw8R/moLhEU6o=
github.com/labstack/gommon v0.3.0 h1:JEeO0bvc78PKdyHxloTKiF8BD5iGrH8T6MSeGvSgob0=
github.com/labstack/gommon v0.3.0/go.mod h1:MULnywXg0yavhxWKc+lOruYdAhDwPK9wf0OL7NoOu+k=
github.com/martinlindhe/base36 v1.0.0 h1:eYsumTah144C0A8P1T/AVSUk5ZoLnhfYFM3OGQxB52A=
github.com/martinlindhe/base36 v1.0.0/go.mod h1:+AtEs8xrBpCeYgSLoY/aJ6Wf37jtBuR0s35750M27+8=
github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
-github.com/mattn/go-colorable v0.1.4 h1:snbPLB8fVfU9iwbbo30TPtbLRzwWu6aJS6Xh4eaaviA=
-github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
+github.com/mattn/go-colorable v0.1.6 h1:6Su7aK7lXmJ/U79bYtBjLNaha4Fs1Rg9plHpcH+vvnE=
+github.com/mattn/go-colorable v0.1.6/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
github.com/mattn/go-isatty v0.0.9/go.mod h1:YNRxwqDuOph6SZLI9vUUz6OYw3QyUt7WiY2yME+cCiQ=
-github.com/mattn/go-isatty v0.0.11/go.mod h1:PhnuNfih5lzO57/f3n+odYbM4JtupLOxQOAqxQCu2WE=
github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY=
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
github.com/microcosm-cc/bluemonday v1.0.2 h1:5lPfLTTAvAbtS0VqT+94yOtFnGfUWYyx0+iToC3Os3s=
@@ -72,24 +73,25 @@ github.com/yuin/gopher-lua v0.0.0-20191220021717-ab39c6098bdb/go.mod h1:gqRgreBU
gitlab.com/golang-commonmark/linkify v0.0.0-20200225224916-64bca66f6ad3 h1:1Coh5BsUBlXoEJmIEaNzVAWrtg9k7/eJzailMQr1grw=
gitlab.com/golang-commonmark/linkify v0.0.0-20200225224916-64bca66f6ad3/go.mod h1:Gn+LZmCrhPECMD3SOKlE+BOHwhOYD9j7WT9NUtkCrC8=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
-golang.org/x/crypto v0.0.0-20191227163750-53104e6ec876/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20200221231518-2aa609cf4a9d h1:1ZiEyfaQIg3Qh0EoqpwAakHVhecoE5wlSg5GjnafJGw=
golang.org/x/crypto v0.0.0-20200221231518-2aa609cf4a9d/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
+golang.org/x/crypto v0.0.0-20200317142112-1b76d66859c6 h1:TjszyFsQsyZNHwdVdZ5m7bjmreu0znc2kRYsEml9/Ww=
+golang.org/x/crypto v0.0.0-20200317142112-1b76d66859c6/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
-golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
-golang.org/x/net v0.0.0-20200225223329-5d076fcf07a8 h1:0hpG1RSqNmKZ60akfzABaMjKAn2762l2+HJyXFT5LMY=
-golang.org/x/net v0.0.0-20200225223329-5d076fcf07a8/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/net v0.0.0-20200301022130-244492dfa37a h1:GuSPYbZzB5/dcLNCwLQLsg3obCJtX9IJhpXkvY7kzk0=
+golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/sys v0.0.0-20190204203706-41f3e6584952/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae h1:/WDfKMnPU+m5M4xB+6x4kaepxRw6jWvR5iDRdvjHgy8=
golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200317113312-5766fd39f98d h1:62ap6LNOjDU6uGmKXHJbSfciMoV+FeI1sRXx/pLDL44=
+golang.org/x/sys v0.0.0-20200317113312-5766fd39f98d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs=
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
diff --git a/plugins/base/public/message.html b/plugins/base/public/message.html
index b537ff0..ed2b1a2 100644
--- a/plugins/base/public/message.html
+++ b/plugins/base/public/message.html
@@ -16,7 +16,8 @@
{{end}}
</h2>
-<form method="post" action="{{.Message.URL}}/move">
+<form method="post" action="/message/{{.Mailbox.Name | pathescape}}/move">
+ <input type="hidden" name="uids" value="{{.Message.Uid}}">
<label for="move-to">Move to:</label>
<select name="to" id="move-to">
{{range .Mailboxes}}
@@ -26,12 +27,14 @@
<input type="submit" value="Move">
</form>
-<form method="post" action="{{.Message.URL}}/delete">
+<form method="post" action="/message/{{.Mailbox.Name | pathescape}}/delete">
+ <input type="hidden" name="uids" value="{{.Message.Uid}}">
<input type="submit" value="Delete">
</form>
{{if .Flags}}
- <form method="post" action="{{.Message.URL}}/flag">
+ <form method="post" action="/message/{{.Mailbox.Name | pathescape}}/flag">
+ <input type="hidden" name="uids" value="{{.Message.Uid}}">
<p>Flags:</p>
{{range $name, $has := .Flags}}
{{if ismutableflag $name}}
diff --git a/plugins/base/routes.go b/plugins/base/routes.go
index 0237634..d2bfe73 100644
--- a/plugins/base/routes.go
+++ b/plugins/base/routes.go
@@ -53,11 +53,11 @@ func registerRoutes(p *koushin.GoPlugin) {
p.GET("/message/:mbox/:uid/edit", handleEdit)
p.POST("/message/:mbox/:uid/edit", handleEdit)
- p.POST("/message/:mbox/:uid/move", handleMove)
+ p.POST("/message/:mbox/move", handleMove)
- p.POST("/message/:mbox/:uid/delete", handleDelete)
+ p.POST("/message/:mbox/delete", handleDelete)
- p.POST("/message/:mbox/:uid/flag", handleSetFlags)
+ p.POST("/message/:mbox/flag", handleSetFlags)
p.GET("/settings", handleSettings)
p.POST("/settings", handleSettings)
@@ -654,7 +654,16 @@ func handleEdit(ctx *koushin.Context) error {
}
func handleMove(ctx *koushin.Context) error {
- mboxName, uid, err := parseMboxAndUid(ctx.Param("mbox"), ctx.Param("uid"))
+ mboxName, err := url.PathUnescape(ctx.Param("mbox"))
+ if err != nil {
+ return echo.NewHTTPError(http.StatusBadRequest, err)
+ }
+
+ formParams, err := ctx.FormParams()
+ if err != nil {
+ return echo.NewHTTPError(http.StatusBadRequest, err)
+ }
+ uids, err := parseUidList(formParams["uids"])
if err != nil {
return echo.NewHTTPError(http.StatusBadRequest, err)
}
@@ -669,7 +678,7 @@ func handleMove(ctx *koushin.Context) error {
}
var seqSet imap.SeqSet
- seqSet.AddNum(uid)
+ seqSet.AddNum(uids...)
if err := mc.UidMoveWithFallback(&seqSet, to); err != nil {
return fmt.Errorf("failed to move message: %v", err)
}
@@ -685,7 +694,16 @@ func handleMove(ctx *koushin.Context) error {
}
func handleDelete(ctx *koushin.Context) error {
- mboxName, uid, err := parseMboxAndUid(ctx.Param("mbox"), ctx.Param("uid"))
+ mboxName, err := url.PathUnescape(ctx.Param("mbox"))
+ if err != nil {
+ return echo.NewHTTPError(http.StatusBadRequest, err)
+ }
+
+ formParams, err := ctx.FormParams()
+ if err != nil {
+ return echo.NewHTTPError(http.StatusBadRequest, err)
+ }
+ uids, err := parseUidList(formParams["uids"])
if err != nil {
return echo.NewHTTPError(http.StatusBadRequest, err)
}
@@ -696,7 +714,7 @@ func handleDelete(ctx *koushin.Context) error {
}
var seqSet imap.SeqSet
- seqSet.AddNum(uid)
+ seqSet.AddNum(uids...)
item := imap.FormatFlagsOp(imap.AddFlags, true)
flags := []interface{}{imap.DeletedFlag}
@@ -724,16 +742,20 @@ func handleDelete(ctx *koushin.Context) error {
}
func handleSetFlags(ctx *koushin.Context) error {
- mboxName, uid, err := parseMboxAndUid(ctx.Param("mbox"), ctx.Param("uid"))
+ mboxName, err := url.PathUnescape(ctx.Param("mbox"))
if err != nil {
return echo.NewHTTPError(http.StatusBadRequest, err)
}
- form, err := ctx.FormParams()
+ formParams, err := ctx.FormParams()
+ if err != nil {
+ return echo.NewHTTPError(http.StatusBadRequest, err)
+ }
+ uids, err := parseUidList(formParams["uids"])
if err != nil {
return echo.NewHTTPError(http.StatusBadRequest, err)
}
- flags, ok := form["flags"]
+ flags, ok := formParams["flags"]
if !ok {
return echo.NewHTTPError(http.StatusBadRequest, "missing 'flags' form values")
}
@@ -756,7 +778,7 @@ func handleSetFlags(ctx *koushin.Context) error {
}
var seqSet imap.SeqSet
- seqSet.AddNum(uid)
+ seqSet.AddNum(uids...)
storeItems := make([]interface{}, len(flags))
for i, f := range flags {
@@ -774,11 +796,11 @@ func handleSetFlags(ctx *koushin.Context) error {
return err
}
- if op == imap.RemoveFlags && len(flags) == 1 && flags[0] == "\\Seen" {
+ if len(uids) != 1 || (op == imap.RemoveFlags && len(flags) == 1 && flags[0] == "\\Seen") {
// Redirecting to the message view would mark the message as read again
return ctx.Redirect(http.StatusFound, fmt.Sprintf("/mailbox/%v", url.PathEscape(mboxName)))
}
- return ctx.Redirect(http.StatusFound, fmt.Sprintf("/message/%v/%v", url.PathEscape(mboxName), uid))
+ return ctx.Redirect(http.StatusFound, fmt.Sprintf("/message/%v/%v", url.PathEscape(mboxName), uids[0]))
}
const settingsKey = "base.settings"
diff --git a/plugins/base/strconv.go b/plugins/base/strconv.go
index 1a32e75..9efa4cd 100644
--- a/plugins/base/strconv.go
+++ b/plugins/base/strconv.go
@@ -27,6 +27,18 @@ func parseMboxAndUid(mboxString, uidString string) (string, uint32, error) {
return mboxName, uid, err
}
+func parseUidList(values []string) ([]uint32, error) {
+ var uids []uint32
+ for _, v := range values {
+ uid, err := parseUid(v)
+ if err != nil {
+ return nil, err
+ }
+ uids = append(uids, uid)
+ }
+ return uids, nil
+}
+
func parsePartPath(s string) ([]int, error) {
if s == "" {
return nil, nil
diff --git a/themes/sourcehut/message.html b/themes/sourcehut/message.html
index af39b15..1e4197f 100644
--- a/themes/sourcehut/message.html
+++ b/themes/sourcehut/message.html
@@ -124,7 +124,8 @@
<details>
<summary>Move to another mailbox</summary>
- <form method="post" action="{{.Message.URL}}/move">
+ <form method="post" action="/message/{{.Mailbox.Name | pathescape}}/move">
+ <input type="hidden" name="uids" value="{{.Message.Uid}}">
<div class="form-group">
<select class="form-control" name="to" id="move-to">
{{range .Mailboxes}}
@@ -140,7 +141,8 @@
<details>
<summary>Delete</summary>
- <form method="post" action="{{.Message.URL}}/delete">
+ <form method="post" action="/message/{{.Mailbox.Name | pathescape}}/delete">
+ <input type="hidden" name="uids" value="{{.Message.Uid}}">
<p>Are you sure?</p>
<div class="pull-right">
<button class="btn btn-danger">Delete</button>
@@ -151,7 +153,8 @@
{{if .Flags}}
<details>
<summary>Edit flags</summary>
- <form method="post" action="{{.Message.URL}}/flag">
+ <form method="post" action="/message/{{.Mailbox.Name | pathescape}}/flag">
+ <input type="hidden" name="uids" value="{{.Message.Uid}}">
<div class="form-group">
{{range $name, $has := .Flags}}
{{if ismutableflag $name}}