You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
93 lines
2.6 KiB
93 lines
2.6 KiB
// Copyright (c) 2022 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 |
|
}
|
|
|