Remove hard coded bodystruct path everywhere

Aerc usually used the path []int{1} if it didn't know what the proper path is.
However this only works for multipart messages and breaks if it isn't one.

This patch removes all the hard coding and extracts the necessary helpers to lib.
This commit is contained in:
Reto Brunner 2020-06-19 17:58:08 +02:00
parent 494bd674a9
commit c574a838fa
8 changed files with 62 additions and 54 deletions

View file

@ -10,6 +10,7 @@ import (
"path"
"strings"
"git.sr.ht/~sircmpwn/aerc/lib"
"git.sr.ht/~sircmpwn/aerc/models"
"git.sr.ht/~sircmpwn/aerc/widgets"
"git.sr.ht/~sircmpwn/aerc/worker/types"
@ -137,12 +138,10 @@ func (forward) Execute(aerc *widgets.Aerc, args []string) error {
}
// TODO: add attachments!
part := findPlaintext(msg.BodyStructure, nil)
part := lib.FindPlaintext(msg.BodyStructure, nil)
if part == nil {
part = findFirstNonMultipart(msg.BodyStructure, nil)
if part == nil {
part = []int{1}
}
part = lib.FindFirstNonMultipart(msg.BodyStructure, nil)
// if it's still nil here, we don't have a multipart msg, that's fine
}
store.FetchBodyPart(msg.Uid, part, func(reader io.Reader) {
buf := new(bytes.Buffer)

View file

@ -8,6 +8,7 @@ import (
"github.com/emersion/go-message/mail"
"github.com/pkg/errors"
"git.sr.ht/~sircmpwn/aerc/lib"
"git.sr.ht/~sircmpwn/aerc/models"
"git.sr.ht/~sircmpwn/aerc/widgets"
"git.sr.ht/~sircmpwn/aerc/worker/types"
@ -107,12 +108,11 @@ func (Recall) Execute(aerc *widgets.Aerc, args []string) error {
part *models.BodyStructure
)
if len(msgInfo.BodyStructure.Parts) != 0 {
path = findPlaintext(msgInfo.BodyStructure, path)
path = lib.FindPlaintext(msgInfo.BodyStructure, path)
}
part, err = msgInfo.BodyStructure.PartAtIndex(path)
if part == nil || err != nil {
part = msgInfo.BodyStructure
path = []int{1}
}
store.FetchBodyPart(msgInfo.Uid, path, func(reader io.Reader) {

View file

@ -10,6 +10,7 @@ import (
"git.sr.ht/~sircmpwn/getopt"
"git.sr.ht/~sircmpwn/aerc/lib"
"git.sr.ht/~sircmpwn/aerc/models"
"git.sr.ht/~sircmpwn/aerc/widgets"
)
@ -169,14 +170,12 @@ func (reply) Execute(aerc *widgets.Aerc, args []string) error {
template = aerc.Config().Templates.QuotedReply
}
part := findPlaintext(msg.BodyStructure, nil)
part := lib.FindPlaintext(msg.BodyStructure, nil)
if part == nil {
// mkey... let's get the first thing that isn't a container
part = findFirstNonMultipart(msg.BodyStructure, nil)
if part == nil {
// give up, use whatever is first
part = []int{1}
}
// if that's still nil it's either not a multipart msg (ok) or
// broken (containers only)
part = lib.FindFirstNonMultipart(msg.BodyStructure, nil)
}
store.FetchBodyPart(msg.Uid, part, func(reader io.Reader) {
buf := new(bytes.Buffer)

View file

@ -2,7 +2,6 @@ package msg
import (
"errors"
"strings"
"git.sr.ht/~sircmpwn/aerc/commands"
"git.sr.ht/~sircmpwn/aerc/lib"
@ -49,34 +48,3 @@ func (h *helper) messages() ([]*models.MessageInfo, error) {
}
return commands.MsgInfoFromUids(store, uid)
}
func findPlaintext(bs *models.BodyStructure, path []int) []int {
for i, part := range bs.Parts {
cur := append(path, i+1)
if strings.ToLower(part.MIMEType) == "text" &&
strings.ToLower(part.MIMESubType) == "plain" {
return cur
}
if strings.ToLower(part.MIMEType) == "multipart" {
if path := findPlaintext(part, cur); path != nil {
return path
}
}
}
return nil
}
func findFirstNonMultipart(bs *models.BodyStructure, path []int) []int {
for i, part := range bs.Parts {
cur := append(path, i+1)
mimetype := strings.ToLower(part.MIMEType)
if mimetype != "multipart" {
return path
} else if mimetype == "multipart" {
if path := findPlaintext(part, cur); path != nil {
return path
}
}
}
return nil
}

38
lib/structure_helpers.go Normal file
View file

@ -0,0 +1,38 @@
package lib
import (
"strings"
"git.sr.ht/~sircmpwn/aerc/models"
)
func FindPlaintext(bs *models.BodyStructure, path []int) []int {
for i, part := range bs.Parts {
cur := append(path, i+1)
if strings.ToLower(part.MIMEType) == "text" &&
strings.ToLower(part.MIMESubType) == "plain" {
return cur
}
if strings.ToLower(part.MIMEType) == "multipart" {
if path := FindPlaintext(part, cur); path != nil {
return path
}
}
}
return nil
}
func FindFirstNonMultipart(bs *models.BodyStructure, path []int) []int {
for i, part := range bs.Parts {
cur := append(path, i+1)
mimetype := strings.ToLower(part.MIMEType)
if mimetype != "multipart" {
return path
} else if mimetype == "multipart" {
if path := FindFirstNonMultipart(part, cur); path != nil {
return path
}
}
}
return nil
}

View file

@ -180,7 +180,7 @@ func createSwitcher(acct *AccountView, switcher *PartSwitcher,
if len(msg.BodyStructure().Parts) == 0 {
switcher.selected = 0
pv, err := NewPartViewer(acct, conf, msg, msg.BodyStructure(), []int{1})
pv, err := NewPartViewer(acct, conf, msg, msg.BodyStructure(), nil)
if err != nil {
return err
}

View file

@ -21,8 +21,9 @@ var dateRe = regexp.MustCompile(`(((Mon|Tue|Wed|Thu|Fri|Sat|Sun))[,]?\s[0-9]{1,2
`([0-9]{4})\s([0-9]{2}):([0-9]{2})(:([0-9]{2}))?\s([\+|\-][0-9]{4})\s?`)
func FetchEntityPartReader(e *message.Entity, index []int) (io.Reader, error) {
if len(index) < 1 {
return nil, fmt.Errorf("no part to read")
if len(index) == 0 {
// non multipart, simply return everything
return bufReader(e)
}
if mpr := e.MultipartReader(); mpr != nil {
idx := 0
@ -41,10 +42,7 @@ func FetchEntityPartReader(e *message.Entity, index []int) (io.Reader, error) {
}
}
}
if index[0] != 1 {
return nil, fmt.Errorf("cannont return non-first part of non-multipart")
}
return bufReader(e)
return nil, fmt.Errorf("FetchEntityPartReader: unexpected code reached")
}
//TODO: the UI doesn't seem to like readers which aren't buffers

View file

@ -10,6 +10,7 @@ import (
"git.sr.ht/~sircmpwn/getopt"
"git.sr.ht/~sircmpwn/aerc/lib"
"git.sr.ht/~sircmpwn/aerc/models"
)
@ -138,7 +139,12 @@ func (w *Worker) searchKey(key uint32, criteria *searchCriteria,
}
if parts&BODY > 0 {
// TODO: select which part to search, maybe look for text/plain
reader, err := message.NewBodyPartReader([]int{1})
mi, err := message.MessageInfo()
if err != nil {
return false, err
}
path := lib.FindFirstNonMultipart(mi.BodyStructure, nil)
reader, err := message.NewBodyPartReader(path)
if err != nil {
return false, err
}