1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137
|
package pencode
import (
"fmt"
"sort"
"strings"
)
var availableEncoders = map[string]Encoder{
"b64encode": Base64Encoder{},
"b64decode": Base64Decoder{},
"filename.tmpl": Template{},
"hexencode": HexEncoder{},
"hexdecode": HexDecoder{},
"htmlescape": HTMLEscaper{},
"htmlunescape": HTMLUnescaper{},
"jsonescape": JSONEscaper{},
"jsonunescape": JSONUnescaper{},
"lower": StrToLower{},
"md5": MD5Hasher{},
"sha1": SHA1Hasher{},
"sha224": SHA224Hasher{},
"sha256": SHA256Hasher{},
"sha384": SHA384Hasher{},
"sha512": SHA512Hasher{},
"unicodedecode": UnicodeDecode{},
"unicodeencodeall": UnicodeEncodeAll{},
"upper": StrToUpper{},
"urlencode": URLEncoder{},
"urldecode": URLDecoder{},
"urlencodeall": URLEncoderAll{},
"utf16": UTF16LEEncode{},
"utf16be": UTF16BEEncode{},
"xmlescape": XMLEscaper{},
"xmlunescape": XMLUnescaper{},
}
type Chain struct {
Encoders []Encoder
initialized bool
actions []string
}
func NewChain() *Chain {
c := Chain{initialized: false}
return &c
}
// Initialize loops through requested names for encoders and sets up the encoder chain. If an unknown encoder is
// requested, error will be returned.
func (c *Chain) Initialize(actions []string) error {
c.actions = actions
c.Encoders = make([]Encoder, 0)
for _, a := range actions {
if ok, err := c.HasEncoder(a); ok {
// Templates are a bit special
if isTemplate(a) {
tenc, err := NewTemplateEncoder(a)
if err != nil {
return err
}
c.Encoders = append(c.Encoders, tenc)
} else {
c.Encoders = append(c.Encoders, availableEncoders[a])
}
} else if err != nil {
return err
} else {
return fmt.Errorf("Encoder %s requested but not found.\n", a)
}
}
c.initialized = true
return nil
}
func (c *Chain) Encode(input []byte) ([]byte, error) {
var err error
if !c.initialized {
return []byte{}, fmt.Errorf("Encoder chain not initialized.\n")
}
for _, e := range c.Encoders {
input, err = e.Encode(input)
if err != nil {
return []byte{}, err
}
}
return input, nil
}
// HasEncoder returns true if encoder with a specified name is configured
func (c *Chain) HasEncoder(name string) (bool, error) {
if _, ok := availableEncoders[name]; ok {
return true, nil
}
// Check for template
if isTemplate(name) {
return hasTemplate(name)
}
return false, nil
}
func (c *Chain) GetEncoders() []string {
// Sort the encoders alphabetically
names := make([]string, 0, len(availableEncoders))
for e := range availableEncoders {
names = append(names, e)
}
sort.Strings(names)
return names
}
// Usage prints the help string for each configured encoder
func (c *Chain) Usage() {
// Calculate maximum keyword length for nice help formatting
max_length := 0
for k := range availableEncoders {
if len(k) > max_length {
max_length = len(k)
}
}
format := fmt.Sprintf(" %%-%ds- %%s\n", max_length+2)
//names := c.GetEncoders()
for _, t := range []string{"encoders", "decoders", "hashes", "other"} {
fmt.Printf("%s\n", strings.ToUpper(t))
list := []string{}
for n, e := range availableEncoders {
if e.Type() == t {
list = append(list, fmt.Sprintf(format, n, e.HelpText()))
}
}
sort.Strings(list)
for _, i := range list {
fmt.Print(i)
}
fmt.Println()
}
}
|