123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157 |
- 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 = ""
- }()
- }
- */
|