Files
proton-bridge/pkg/message/parser/walker.go
2020-09-11 11:41:03 +02:00

94 lines
2.6 KiB
Go

// Copyright (c) 2020 Proton Technologies AG
//
// This file is part of ProtonMail Bridge.
//
// ProtonMail Bridge is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// ProtonMail Bridge is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with ProtonMail Bridge. If not, see <https://www.gnu.org/licenses/>.
package parser
import "regexp"
type Walker struct {
root *Part
handlers []*handler
defaultHandler HandlerFunc
}
func newWalker(root *Part) *Walker {
return &Walker{
root: root,
defaultHandler: func(*Part) error { return nil },
}
}
func (w *Walker) Walk() (err error) {
return w.walkOverPart(w.root)
}
func (w *Walker) walkOverPart(p *Part) error {
if err := w.getHandlerFunc(p)(p); err != nil {
return err
}
for _, child := range p.children {
if err := w.walkOverPart(child); err != nil {
return err
}
}
return nil
}
// RegisterDefaultHandler registers a handler that will be called on every part
// that doesn't match a registered content type/disposition handler.
func (w *Walker) RegisterDefaultHandler(fn HandlerFunc) *Walker {
w.defaultHandler = fn
return w
}
// RegisterContentTypeHandler registers a handler that will be called when a
// part's content type matches the given regular expression.
// If a part matches multiple handlers, the one registered first will be chosen.
func (w *Walker) RegisterContentTypeHandler(typeRegExp string, fn HandlerFunc) *Walker {
w.handlers = append(w.handlers, &handler{
typeRegExp: regexp.MustCompile(typeRegExp),
fn: fn,
})
return w
}
// RegisterContentDispositionHandler registers a handler that will be called
// when a part's content disposition matches the given regular expression.
// If a part matches multiple handlers, the one registered first will be chosen.
func (w *Walker) RegisterContentDispositionHandler(dispRegExp string, fn HandlerFunc) *Walker {
w.handlers = append(w.handlers, &handler{
dispRegExp: regexp.MustCompile(dispRegExp),
fn: fn,
})
return w
}
func (w *Walker) getHandlerFunc(p *Part) HandlerFunc {
for _, handler := range w.handlers {
if handler.matchPart(p) {
return handler.fn
}
}
return w.defaultHandler
}