mirror of
https://github.com/Luzifer/cloudkeys-go.git
synced 2024-11-08 22:20:05 +00:00
157 lines
4.3 KiB
Go
157 lines
4.3 KiB
Go
package pongo2
|
|
|
|
import (
|
|
"bytes"
|
|
"io"
|
|
"io/ioutil"
|
|
"log"
|
|
"os"
|
|
"path/filepath"
|
|
|
|
"github.com/juju/errors"
|
|
)
|
|
|
|
// LocalFilesystemLoader represents a local filesystem loader with basic
|
|
// BaseDirectory capabilities. The access to the local filesystem is unrestricted.
|
|
type LocalFilesystemLoader struct {
|
|
baseDir string
|
|
}
|
|
|
|
// MustNewLocalFileSystemLoader creates a new LocalFilesystemLoader instance
|
|
// and panics if there's any error during instantiation. The parameters
|
|
// are the same like NewLocalFileSystemLoader.
|
|
func MustNewLocalFileSystemLoader(baseDir string) *LocalFilesystemLoader {
|
|
fs, err := NewLocalFileSystemLoader(baseDir)
|
|
if err != nil {
|
|
log.Panic(err)
|
|
}
|
|
return fs
|
|
}
|
|
|
|
// NewLocalFileSystemLoader creates a new LocalFilesystemLoader and allows
|
|
// templatesto be loaded from disk (unrestricted). If any base directory
|
|
// is given (or being set using SetBaseDir), this base directory is being used
|
|
// for path calculation in template inclusions/imports. Otherwise the path
|
|
// is calculated based relatively to the including template's path.
|
|
func NewLocalFileSystemLoader(baseDir string) (*LocalFilesystemLoader, error) {
|
|
fs := &LocalFilesystemLoader{}
|
|
if baseDir != "" {
|
|
if err := fs.SetBaseDir(baseDir); err != nil {
|
|
return nil, err
|
|
}
|
|
}
|
|
return fs, nil
|
|
}
|
|
|
|
// SetBaseDir sets the template's base directory. This directory will
|
|
// be used for any relative path in filters, tags and From*-functions to determine
|
|
// your template. See the comment for NewLocalFileSystemLoader as well.
|
|
func (fs *LocalFilesystemLoader) SetBaseDir(path string) error {
|
|
// Make the path absolute
|
|
if !filepath.IsAbs(path) {
|
|
abs, err := filepath.Abs(path)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
path = abs
|
|
}
|
|
|
|
// Check for existence
|
|
fi, err := os.Stat(path)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if !fi.IsDir() {
|
|
return errors.Errorf("The given path '%s' is not a directory.", path)
|
|
}
|
|
|
|
fs.baseDir = path
|
|
return nil
|
|
}
|
|
|
|
// Get reads the path's content from your local filesystem.
|
|
func (fs *LocalFilesystemLoader) Get(path string) (io.Reader, error) {
|
|
buf, err := ioutil.ReadFile(path)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return bytes.NewReader(buf), nil
|
|
}
|
|
|
|
// 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 (fs *LocalFilesystemLoader) Abs(base, name string) string {
|
|
if filepath.IsAbs(name) {
|
|
return name
|
|
}
|
|
|
|
// Our own base dir has always priority; if there's none
|
|
// we use the path provided in base.
|
|
var err error
|
|
if fs.baseDir == "" {
|
|
if base == "" {
|
|
base, err = os.Getwd()
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
return filepath.Join(base, name)
|
|
}
|
|
|
|
return filepath.Join(filepath.Dir(base), name)
|
|
}
|
|
|
|
return filepath.Join(fs.baseDir, name)
|
|
}
|
|
|
|
// SandboxedFilesystemLoader is still WIP.
|
|
type SandboxedFilesystemLoader struct {
|
|
*LocalFilesystemLoader
|
|
}
|
|
|
|
// NewSandboxedFilesystemLoader creates a new sandboxed local file system instance.
|
|
func NewSandboxedFilesystemLoader(baseDir string) (*SandboxedFilesystemLoader, error) {
|
|
fs, err := NewLocalFileSystemLoader(baseDir)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return &SandboxedFilesystemLoader{
|
|
LocalFilesystemLoader: fs,
|
|
}, nil
|
|
}
|
|
|
|
// Move sandbox to a virtual fs
|
|
|
|
/*
|
|
if len(set.SandboxDirectories) > 0 {
|
|
defer func() {
|
|
// Remove any ".." or other crap
|
|
resolvedPath = filepath.Clean(resolvedPath)
|
|
|
|
// Make the path absolute
|
|
absPath, err := filepath.Abs(resolvedPath)
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
resolvedPath = absPath
|
|
|
|
// Check against the sandbox directories (once one pattern matches, we're done and can allow it)
|
|
for _, pattern := range set.SandboxDirectories {
|
|
matched, err := filepath.Match(pattern, resolvedPath)
|
|
if err != nil {
|
|
panic("Wrong sandbox directory match pattern (see http://golang.org/pkg/path/filepath/#Match).")
|
|
}
|
|
if matched {
|
|
// OK!
|
|
return
|
|
}
|
|
}
|
|
|
|
// No pattern matched, we have to log+deny the request
|
|
set.logf("Access attempt outside of the sandbox directories (blocked): '%s'", resolvedPath)
|
|
resolvedPath = ""
|
|
}()
|
|
}
|
|
*/
|