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:
parent
494bd674a9
commit
c574a838fa
8 changed files with 62 additions and 54 deletions
|
@ -10,6 +10,7 @@ import (
|
||||||
"path"
|
"path"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"git.sr.ht/~sircmpwn/aerc/lib"
|
||||||
"git.sr.ht/~sircmpwn/aerc/models"
|
"git.sr.ht/~sircmpwn/aerc/models"
|
||||||
"git.sr.ht/~sircmpwn/aerc/widgets"
|
"git.sr.ht/~sircmpwn/aerc/widgets"
|
||||||
"git.sr.ht/~sircmpwn/aerc/worker/types"
|
"git.sr.ht/~sircmpwn/aerc/worker/types"
|
||||||
|
@ -137,12 +138,10 @@ func (forward) Execute(aerc *widgets.Aerc, args []string) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: add attachments!
|
// TODO: add attachments!
|
||||||
part := findPlaintext(msg.BodyStructure, nil)
|
part := lib.FindPlaintext(msg.BodyStructure, nil)
|
||||||
if part == nil {
|
if part == nil {
|
||||||
part = findFirstNonMultipart(msg.BodyStructure, nil)
|
part = lib.FindFirstNonMultipart(msg.BodyStructure, nil)
|
||||||
if part == nil {
|
// if it's still nil here, we don't have a multipart msg, that's fine
|
||||||
part = []int{1}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
store.FetchBodyPart(msg.Uid, part, func(reader io.Reader) {
|
store.FetchBodyPart(msg.Uid, part, func(reader io.Reader) {
|
||||||
buf := new(bytes.Buffer)
|
buf := new(bytes.Buffer)
|
||||||
|
|
|
@ -8,6 +8,7 @@ import (
|
||||||
"github.com/emersion/go-message/mail"
|
"github.com/emersion/go-message/mail"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
|
|
||||||
|
"git.sr.ht/~sircmpwn/aerc/lib"
|
||||||
"git.sr.ht/~sircmpwn/aerc/models"
|
"git.sr.ht/~sircmpwn/aerc/models"
|
||||||
"git.sr.ht/~sircmpwn/aerc/widgets"
|
"git.sr.ht/~sircmpwn/aerc/widgets"
|
||||||
"git.sr.ht/~sircmpwn/aerc/worker/types"
|
"git.sr.ht/~sircmpwn/aerc/worker/types"
|
||||||
|
@ -107,12 +108,11 @@ func (Recall) Execute(aerc *widgets.Aerc, args []string) error {
|
||||||
part *models.BodyStructure
|
part *models.BodyStructure
|
||||||
)
|
)
|
||||||
if len(msgInfo.BodyStructure.Parts) != 0 {
|
if len(msgInfo.BodyStructure.Parts) != 0 {
|
||||||
path = findPlaintext(msgInfo.BodyStructure, path)
|
path = lib.FindPlaintext(msgInfo.BodyStructure, path)
|
||||||
}
|
}
|
||||||
part, err = msgInfo.BodyStructure.PartAtIndex(path)
|
part, err = msgInfo.BodyStructure.PartAtIndex(path)
|
||||||
if part == nil || err != nil {
|
if part == nil || err != nil {
|
||||||
part = msgInfo.BodyStructure
|
part = msgInfo.BodyStructure
|
||||||
path = []int{1}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
store.FetchBodyPart(msgInfo.Uid, path, func(reader io.Reader) {
|
store.FetchBodyPart(msgInfo.Uid, path, func(reader io.Reader) {
|
||||||
|
|
|
@ -10,6 +10,7 @@ import (
|
||||||
|
|
||||||
"git.sr.ht/~sircmpwn/getopt"
|
"git.sr.ht/~sircmpwn/getopt"
|
||||||
|
|
||||||
|
"git.sr.ht/~sircmpwn/aerc/lib"
|
||||||
"git.sr.ht/~sircmpwn/aerc/models"
|
"git.sr.ht/~sircmpwn/aerc/models"
|
||||||
"git.sr.ht/~sircmpwn/aerc/widgets"
|
"git.sr.ht/~sircmpwn/aerc/widgets"
|
||||||
)
|
)
|
||||||
|
@ -169,14 +170,12 @@ func (reply) Execute(aerc *widgets.Aerc, args []string) error {
|
||||||
template = aerc.Config().Templates.QuotedReply
|
template = aerc.Config().Templates.QuotedReply
|
||||||
}
|
}
|
||||||
|
|
||||||
part := findPlaintext(msg.BodyStructure, nil)
|
part := lib.FindPlaintext(msg.BodyStructure, nil)
|
||||||
if part == nil {
|
if part == nil {
|
||||||
// mkey... let's get the first thing that isn't a container
|
// mkey... let's get the first thing that isn't a container
|
||||||
part = findFirstNonMultipart(msg.BodyStructure, nil)
|
// if that's still nil it's either not a multipart msg (ok) or
|
||||||
if part == nil {
|
// broken (containers only)
|
||||||
// give up, use whatever is first
|
part = lib.FindFirstNonMultipart(msg.BodyStructure, nil)
|
||||||
part = []int{1}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
store.FetchBodyPart(msg.Uid, part, func(reader io.Reader) {
|
store.FetchBodyPart(msg.Uid, part, func(reader io.Reader) {
|
||||||
buf := new(bytes.Buffer)
|
buf := new(bytes.Buffer)
|
||||||
|
|
|
@ -2,7 +2,6 @@ package msg
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"strings"
|
|
||||||
|
|
||||||
"git.sr.ht/~sircmpwn/aerc/commands"
|
"git.sr.ht/~sircmpwn/aerc/commands"
|
||||||
"git.sr.ht/~sircmpwn/aerc/lib"
|
"git.sr.ht/~sircmpwn/aerc/lib"
|
||||||
|
@ -49,34 +48,3 @@ func (h *helper) messages() ([]*models.MessageInfo, error) {
|
||||||
}
|
}
|
||||||
return commands.MsgInfoFromUids(store, uid)
|
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
38
lib/structure_helpers.go
Normal 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
|
||||||
|
}
|
|
@ -180,7 +180,7 @@ func createSwitcher(acct *AccountView, switcher *PartSwitcher,
|
||||||
|
|
||||||
if len(msg.BodyStructure().Parts) == 0 {
|
if len(msg.BodyStructure().Parts) == 0 {
|
||||||
switcher.selected = 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 {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
|
@ -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?`)
|
`([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) {
|
func FetchEntityPartReader(e *message.Entity, index []int) (io.Reader, error) {
|
||||||
if len(index) < 1 {
|
if len(index) == 0 {
|
||||||
return nil, fmt.Errorf("no part to read")
|
// non multipart, simply return everything
|
||||||
|
return bufReader(e)
|
||||||
}
|
}
|
||||||
if mpr := e.MultipartReader(); mpr != nil {
|
if mpr := e.MultipartReader(); mpr != nil {
|
||||||
idx := 0
|
idx := 0
|
||||||
|
@ -41,10 +42,7 @@ func FetchEntityPartReader(e *message.Entity, index []int) (io.Reader, error) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if index[0] != 1 {
|
return nil, fmt.Errorf("FetchEntityPartReader: unexpected code reached")
|
||||||
return nil, fmt.Errorf("cannont return non-first part of non-multipart")
|
|
||||||
}
|
|
||||||
return bufReader(e)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//TODO: the UI doesn't seem to like readers which aren't buffers
|
//TODO: the UI doesn't seem to like readers which aren't buffers
|
||||||
|
|
|
@ -10,6 +10,7 @@ import (
|
||||||
|
|
||||||
"git.sr.ht/~sircmpwn/getopt"
|
"git.sr.ht/~sircmpwn/getopt"
|
||||||
|
|
||||||
|
"git.sr.ht/~sircmpwn/aerc/lib"
|
||||||
"git.sr.ht/~sircmpwn/aerc/models"
|
"git.sr.ht/~sircmpwn/aerc/models"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -138,7 +139,12 @@ func (w *Worker) searchKey(key uint32, criteria *searchCriteria,
|
||||||
}
|
}
|
||||||
if parts&BODY > 0 {
|
if parts&BODY > 0 {
|
||||||
// TODO: select which part to search, maybe look for text/plain
|
// 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 {
|
if err != nil {
|
||||||
return false, err
|
return false, err
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue