...

Source file src/github.com/noirbizarre/gonja/loaders/filesystem.go

Documentation: github.com/noirbizarre/gonja/loaders

     1  package loaders
     2  
     3  import (
     4  	"bytes"
     5  	"io"
     6  	"io/ioutil"
     7  	"log"
     8  	"os"
     9  	"path/filepath"
    10  
    11  	"github.com/pkg/errors"
    12  )
    13  
    14  // FilesystemLoader represents a local filesystem loader with basic
    15  // BaseDirectory capabilities. The access to the local filesystem is unrestricted.
    16  type FilesystemLoader struct {
    17  	root string
    18  }
    19  
    20  // MustNewFileSystemLoader creates a new FilesystemLoader instance
    21  // and panics if there's any error during instantiation. The parameters
    22  // are the same like NewFileSystemLoader.
    23  func MustNewFileSystemLoader(root string) *FilesystemLoader {
    24  	fs, err := NewFileSystemLoader(root)
    25  	if err != nil {
    26  		log.Panic(err)
    27  	}
    28  	return fs
    29  }
    30  
    31  // NewFileSystemLoader creates a new FilesystemLoader and allows
    32  // templatesto be loaded from disk (unrestricted). If any base directory
    33  // is given (or being set using SetBaseDir), this base directory is being used
    34  // for path calculation in template inclusions/imports. Otherwise the path
    35  // is calculated based relatively to the including template's path.
    36  func NewFileSystemLoader(root string) (*FilesystemLoader, error) {
    37  	fs := &FilesystemLoader{}
    38  	if root != "" {
    39  		if err := fs.SetBaseDir(root); err != nil {
    40  			return nil, err
    41  		}
    42  	}
    43  	return fs, nil
    44  }
    45  
    46  // SetBaseDir sets the template's base directory. This directory will
    47  // be used for any relative path in filters, tags and From*-functions to determine
    48  // your template. See the comment for NewFileSystemLoader as well.
    49  func (fs *FilesystemLoader) SetBaseDir(path string) error {
    50  	// Make the path absolute
    51  	if !filepath.IsAbs(path) {
    52  		abs, err := filepath.Abs(path)
    53  		if err != nil {
    54  			return err
    55  		}
    56  		path = abs
    57  	}
    58  
    59  	// Check for existence
    60  	fi, err := os.Stat(path)
    61  	if err != nil {
    62  		return err
    63  	}
    64  	if !fi.IsDir() {
    65  		return errors.Errorf("The given path '%s' is not a directory.", path)
    66  	}
    67  
    68  	fs.root = path
    69  	return nil
    70  }
    71  
    72  // Get reads the path's content from your local filesystem.
    73  func (fs *FilesystemLoader) Get(path string) (io.Reader, error) {
    74  	realPath, err := fs.Path(path)
    75  	if err != nil {
    76  		return nil, err
    77  	}
    78  	buf, err := ioutil.ReadFile(realPath)
    79  	if err != nil {
    80  		return nil, err
    81  	}
    82  	return bytes.NewReader(buf), nil
    83  }
    84  
    85  // Path resolves a filename relative to the base directory. Absolute paths are allowed.
    86  // When there's no base dir set, the absolute path to the filename
    87  // will be calculated based on either the provided base directory (which
    88  // might be a path of a template which includes another template) or
    89  // the current working directory.
    90  func (fs *FilesystemLoader) Path(name string) (string, error) {
    91  	if filepath.IsAbs(name) {
    92  		return name, nil
    93  	}
    94  
    95  	// root := fs.root
    96  	if fs.root == "" {
    97  		root, err := os.Getwd()
    98  		if err != nil {
    99  			return "", err
   100  		}
   101  		return filepath.Join(root, name), nil
   102  	} else {
   103  		return filepath.Join(fs.root, name), nil
   104  	}
   105  
   106  	// // Our own base dir has always priority; if there's none
   107  	// // we use the path provided in base.
   108  	// var err error
   109  	// if fs.root == "" {
   110  	// 	if base == "" {
   111  	// 		base, err = os.Getwd()
   112  	// 		if err != nil {
   113  	// 			panic(err)
   114  	// 		}
   115  	// 		return filepath.Join(base, name)
   116  	// 	}
   117  
   118  	// 	return filepath.Join(filepath.Dir(base), name)
   119  	// }
   120  
   121  	// return filepath.Join(fs.root, name)
   122  }
   123  
   124  // SandboxedFilesystemLoader is still WIP.
   125  type SandboxedFilesystemLoader struct {
   126  	*FilesystemLoader
   127  }
   128  
   129  // NewSandboxedFilesystemLoader creates a new sandboxed local file system instance.
   130  func NewSandboxedFilesystemLoader(root string) (*SandboxedFilesystemLoader, error) {
   131  	fs, err := NewFileSystemLoader(root)
   132  	if err != nil {
   133  		return nil, err
   134  	}
   135  	return &SandboxedFilesystemLoader{
   136  		FilesystemLoader: fs,
   137  	}, nil
   138  }
   139  
   140  // Move sandbox to a virtual fs
   141  
   142  /*
   143  if len(set.SandboxDirectories) > 0 {
   144      defer func() {
   145          // Remove any ".." or other crap
   146          resolvedPath = filepath.Clean(resolvedPath)
   147  
   148          // Make the path absolute
   149          absPath, err := filepath.Abs(resolvedPath)
   150          if err != nil {
   151              panic(err)
   152          }
   153          resolvedPath = absPath
   154  
   155          // Check against the sandbox directories (once one pattern matches, we're done and can allow it)
   156          for _, pattern := range set.SandboxDirectories {
   157              matched, err := filepath.Match(pattern, resolvedPath)
   158              if err != nil {
   159                  panic("Wrong sandbox directory match pattern (see http://golang.org/pkg/path/filepath/#Match).")
   160              }
   161              if matched {
   162                  // OK!
   163                  return
   164              }
   165          }
   166  
   167          // No pattern matched, we have to log+deny the request
   168          set.logf("Access attempt outside of the sandbox directories (blocked): '%s'", resolvedPath)
   169          resolvedPath = ""
   170      }()
   171  }
   172  */
   173  

View as plain text