aboutsummaryrefslogtreecommitdiff
path: root/plugins
diff options
context:
space:
mode:
Diffstat (limited to 'plugins')
-rw-r--r--plugins/base/public/message.html9
-rw-r--r--plugins/base/routes.go48
-rw-r--r--plugins/base/strconv.go12
3 files changed, 53 insertions, 16 deletions
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