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
|
package template
import (
"bytes"
"errors"
"fmt"
"io"
"os"
"path/filepath"
"strings"
)
// ChrootLoader is a pong2 compatible file loader which restricts all accesses to a directory.
type ChrootLoader struct {
Path string
}
// Abs resolves a filename relative to the base directory. Absolute paths are allowed.
// When there's no base dir set, the absolute path to the filename
// will be calculated based on either the provided base directory (which
// might be a path of a template which includes another template) or
// the current working directory.
func (l ChrootLoader) Abs(base string, name string) string {
return filepath.Clean(fmt.Sprintf("%s/%s", l.Path, name))
}
// Get reads the path's content from your local filesystem.
func (l ChrootLoader) Get(path string) (io.Reader, error) {
// Get the full path
path, err := filepath.EvalSymlinks(path)
if err != nil {
return nil, err
}
basePath, err := filepath.EvalSymlinks(l.Path)
if err != nil {
return nil, err
}
// Validate that we're under the expected prefix
if !strings.HasPrefix(path, basePath) {
return nil, errors.New("Attempting to access a file outside the instance")
}
// Open and read the file
buf, err := os.ReadFile(path)
if err != nil {
return nil, err
}
return bytes.NewReader(buf), nil
}
|