msgpart: factorize mime type and filename construction
Reduce code duplication. Signed-off-by: Robin Jarry <robin@jarry.cc> Acked-by: Moritz Poldrack <moritz@poldrack.dev>
This commit is contained in:
parent
a4b80bcc8b
commit
9bd2e0c84f
8 changed files with 30 additions and 28 deletions
|
@ -198,7 +198,7 @@ func (forward) Execute(aerc *widgets.Aerc, args []string) error {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
store.FetchBodyPart(msg.Uid, p, func(reader io.Reader) {
|
store.FetchBodyPart(msg.Uid, p, func(reader io.Reader) {
|
||||||
mime := fmt.Sprintf("%s/%s", bs.MIMEType, bs.MIMESubType)
|
mime := bs.FullMIMEType()
|
||||||
params := lib.SetUtf8Charset(bs.Params)
|
params := lib.SetUtf8Charset(bs.Params)
|
||||||
name, ok := params["name"]
|
name, ok := params["name"]
|
||||||
if !ok {
|
if !ok {
|
||||||
|
|
|
@ -204,7 +204,7 @@ func (Recall) Execute(aerc *widgets.Aerc, args []string) error {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
msg.FetchBodyPart(p, func(reader io.Reader) {
|
msg.FetchBodyPart(p, func(reader io.Reader) {
|
||||||
mime := fmt.Sprintf("%s/%s", bs.MIMEType, bs.MIMESubType)
|
mime := bs.FullMIMEType()
|
||||||
params := lib.SetUtf8Charset(bs.Params)
|
params := lib.SetUtf8Charset(bs.Params)
|
||||||
name, ok := params["name"]
|
name, ok := params["name"]
|
||||||
if !ok {
|
if !ok {
|
||||||
|
|
|
@ -326,7 +326,7 @@ func addMimeType(msg *models.MessageInfo, part []int,
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
orig.MIMEType = fmt.Sprintf("%s/%s", bs.MIMEType, bs.MIMESubType)
|
orig.MIMEType = bs.FullMIMEType()
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
package msgview
|
package msgview
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
|
||||||
"io"
|
"io"
|
||||||
"mime"
|
"mime"
|
||||||
"os"
|
"os"
|
||||||
|
@ -52,7 +51,7 @@ func (Open) Execute(aerc *widgets.Aerc, args []string) error {
|
||||||
|
|
||||||
// try to determine the correct extension based on mimetype
|
// try to determine the correct extension based on mimetype
|
||||||
if part, err := mv.MessageView().BodyStructure().PartAtIndex(p.Index); err == nil {
|
if part, err := mv.MessageView().BodyStructure().PartAtIndex(p.Index); err == nil {
|
||||||
mimeType = fmt.Sprintf("%s/%s", part.MIMEType, part.MIMESubType)
|
mimeType = part.FullMIMEType()
|
||||||
if exts, _ := mime.ExtensionsByType(mimeType); len(exts) > 0 {
|
if exts, _ := mime.ExtensionsByType(mimeType); len(exts) > 0 {
|
||||||
extension = exts[0]
|
extension = exts[0]
|
||||||
}
|
}
|
||||||
|
|
|
@ -215,12 +215,7 @@ func isAbsPath(path string) bool {
|
||||||
// generateFilename tries to get the filename from the given part.
|
// generateFilename tries to get the filename from the given part.
|
||||||
// if that fails it will fallback to a generated one based on the date
|
// if that fails it will fallback to a generated one based on the date
|
||||||
func generateFilename(part *models.BodyStructure) string {
|
func generateFilename(part *models.BodyStructure) string {
|
||||||
var filename string
|
filename := part.FileName()
|
||||||
if fn, ok := part.DispositionParams["filename"]; ok {
|
|
||||||
filename = fn
|
|
||||||
} else if fn, ok := part.Params["name"]; ok {
|
|
||||||
filename = fn
|
|
||||||
}
|
|
||||||
// Some MUAs send attachments with names like /some/stupid/idea/happy.jpeg
|
// Some MUAs send attachments with names like /some/stupid/idea/happy.jpeg
|
||||||
// Assuming non hostile intent it does make sense to use just the last
|
// Assuming non hostile intent it does make sense to use just the last
|
||||||
// portion of the pathname as the filename for saving it.
|
// portion of the pathname as the filename for saving it.
|
||||||
|
|
|
@ -9,8 +9,7 @@ import (
|
||||||
func FindPlaintext(bs *models.BodyStructure, path []int) []int {
|
func FindPlaintext(bs *models.BodyStructure, path []int) []int {
|
||||||
for i, part := range bs.Parts {
|
for i, part := range bs.Parts {
|
||||||
cur := append(path, i+1) //nolint:gocritic // intentional append to different slice
|
cur := append(path, i+1) //nolint:gocritic // intentional append to different slice
|
||||||
if strings.ToLower(part.MIMEType) == "text" &&
|
if part.FullMIMEType() == "text/plain" {
|
||||||
strings.ToLower(part.MIMESubType) == "plain" {
|
|
||||||
return cur
|
return cur
|
||||||
}
|
}
|
||||||
if strings.ToLower(part.MIMEType) == "multipart" {
|
if strings.ToLower(part.MIMEType) == "multipart" {
|
||||||
|
@ -25,8 +24,7 @@ func FindPlaintext(bs *models.BodyStructure, path []int) []int {
|
||||||
func FindCalendartext(bs *models.BodyStructure, path []int) []int {
|
func FindCalendartext(bs *models.BodyStructure, path []int) []int {
|
||||||
for i, part := range bs.Parts {
|
for i, part := range bs.Parts {
|
||||||
cur := append(path, i+1) //nolint:gocritic // intentional append to different slice
|
cur := append(path, i+1) //nolint:gocritic // intentional append to different slice
|
||||||
if strings.ToLower(part.MIMEType) == "text" &&
|
if part.FullMIMEType() == "text/calendar" {
|
||||||
strings.ToLower(part.MIMESubType) == "calendar" {
|
|
||||||
return cur
|
return cur
|
||||||
}
|
}
|
||||||
if strings.ToLower(part.MIMEType) == "multipart" {
|
if strings.ToLower(part.MIMEType) == "multipart" {
|
||||||
|
|
|
@ -4,6 +4,7 @@ import (
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/emersion/go-message/mail"
|
"github.com/emersion/go-message/mail"
|
||||||
|
@ -175,6 +176,21 @@ func (bs *BodyStructure) PartAtIndex(index []int) (*BodyStructure, error) {
|
||||||
return bs.Parts[curidx].PartAtIndex(rest)
|
return bs.Parts[curidx].PartAtIndex(rest)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (bs *BodyStructure) FullMIMEType() string {
|
||||||
|
mime := fmt.Sprintf("%s/%s", bs.MIMEType, bs.MIMESubType)
|
||||||
|
return strings.ToLower(mime)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (bs *BodyStructure) FileName() string {
|
||||||
|
if filename, ok := bs.DispositionParams["filename"]; ok {
|
||||||
|
return filename
|
||||||
|
} else if filename, ok := bs.Params["name"]; ok {
|
||||||
|
// workaround golang not supporting RFC2231 besides ASCII and UTF8
|
||||||
|
return filename
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
type Envelope struct {
|
type Envelope struct {
|
||||||
Date time.Time
|
Date time.Time
|
||||||
Subject string
|
Subject string
|
||||||
|
|
|
@ -230,8 +230,7 @@ func createSwitcher(acct *AccountView, switcher *PartSwitcher,
|
||||||
if switcher.selected == -1 && pv.part.MIMEType != "multipart" {
|
if switcher.selected == -1 && pv.part.MIMEType != "multipart" {
|
||||||
switcher.selected = i
|
switcher.selected = i
|
||||||
}
|
}
|
||||||
mime := strings.ToLower(pv.part.MIMEType) +
|
mime := pv.part.FullMIMEType()
|
||||||
"/" + strings.ToLower(pv.part.MIMESubType)
|
|
||||||
for idx, m := range conf.Viewer.Alternatives {
|
for idx, m := range conf.Viewer.Alternatives {
|
||||||
if m != mime {
|
if m != mime {
|
||||||
continue
|
continue
|
||||||
|
@ -422,13 +421,9 @@ func (ps *PartSwitcher) Draw(ctx *ui.Context) {
|
||||||
style = ps.mv.uiConfig.GetStyleSelected(config.STYLE_DEFAULT)
|
style = ps.mv.uiConfig.GetStyleSelected(config.STYLE_DEFAULT)
|
||||||
}
|
}
|
||||||
ctx.Fill(0, y+i, ctx.Width(), 1, ' ', style)
|
ctx.Fill(0, y+i, ctx.Width(), 1, ' ', style)
|
||||||
name := fmt.Sprintf("%s/%s",
|
name := part.part.FullMIMEType()
|
||||||
strings.ToLower(part.part.MIMEType),
|
filename := part.part.FileName()
|
||||||
strings.ToLower(part.part.MIMESubType))
|
if filename != "" {
|
||||||
if filename, ok := part.part.DispositionParams["filename"]; ok {
|
|
||||||
name += fmt.Sprintf(" (%s)", filename)
|
|
||||||
} else if filename, ok := part.part.Params["name"]; ok {
|
|
||||||
// workaround golang not supporting RFC2231 besides ASCII and UTF8
|
|
||||||
name += fmt.Sprintf(" (%s)", filename)
|
name += fmt.Sprintf(" (%s)", filename)
|
||||||
}
|
}
|
||||||
ctx.Printf(len(part.index)*2, y+i, style, "%s", name)
|
ctx.Printf(len(part.index)*2, y+i, style, "%s", name)
|
||||||
|
@ -547,8 +542,7 @@ func NewPartViewer(acct *AccountView, conf *config.AercConfig,
|
||||||
|
|
||||||
info := msg.MessageInfo()
|
info := msg.MessageInfo()
|
||||||
for _, f := range conf.Filters {
|
for _, f := range conf.Filters {
|
||||||
mime := strings.ToLower(part.MIMEType) +
|
mime := part.FullMIMEType()
|
||||||
"/" + strings.ToLower(part.MIMESubType)
|
|
||||||
switch f.FilterType {
|
switch f.FilterType {
|
||||||
case config.FILTER_MIMETYPE:
|
case config.FILTER_MIMETYPE:
|
||||||
if fnmatch.Match(f.Filter, mime, 0) {
|
if fnmatch.Match(f.Filter, mime, 0) {
|
||||||
|
@ -813,8 +807,8 @@ func newNoFilterConfigured(pv *PartViewer) *ui.Grid {
|
||||||
|
|
||||||
uiConfig := pv.conf.Ui
|
uiConfig := pv.conf.Ui
|
||||||
|
|
||||||
noFilter := fmt.Sprintf(`No filter configured for this mimetype ('%s/%s')
|
noFilter := fmt.Sprintf(`No filter configured for this mimetype ('%s')
|
||||||
What would you like to do?`, pv.part.MIMEType, pv.part.MIMESubType)
|
What would you like to do?`, pv.part.FullMIMEType())
|
||||||
grid.AddChild(ui.NewText(noFilter,
|
grid.AddChild(ui.NewText(noFilter,
|
||||||
uiConfig.GetStyle(config.STYLE_TITLE))).At(0, 0)
|
uiConfig.GetStyle(config.STYLE_TITLE))).At(0, 0)
|
||||||
for i, action := range actions {
|
for i, action := range actions {
|
||||||
|
|
Loading…
Reference in a new issue