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 2
func MustNewFileSystemLoader(root string) *FilesystemLoader {
24 2
	fs, err := NewFileSystemLoader(root)
25 2
	if err != nil {
26 0
		log.Panic(err)
27 0
	}
28 2
	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 2
func NewFileSystemLoader(root string) (*FilesystemLoader, error) {
37 2
	fs := &FilesystemLoader{}
38 2
	if root != "" {
39 2
		if err := fs.SetBaseDir(root); err != nil {
40 0
			return nil, err
41 0
		}
42
	}
43 2
	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 2
func (fs *FilesystemLoader) SetBaseDir(path string) error {
50 1
	// Make the path absolute
51 2
	if !filepath.IsAbs(path) {
52 2
		abs, err := filepath.Abs(path)
53 2
		if err != nil {
54 0
			return err
55 0
		}
56 2
		path = abs
57
	}
58

59
	// Check for existence
60 2
	fi, err := os.Stat(path)
61 2
	if err != nil {
62 0
		return err
63 0
	}
64 2
	if !fi.IsDir() {
65 0
		return errors.Errorf("The given path '%s' is not a directory.", path)
66 0
	}
67

68 2
	fs.root = path
69 2
	return nil
70
}
71

72
// Get reads the path's content from your local filesystem.
73 2
func (fs *FilesystemLoader) Get(path string) (io.Reader, error) {
74 2
	realPath, err := fs.Path(path)
75 2
	if err != nil {
76 0
		return nil, err
77 0
	}
78 2
	buf, err := ioutil.ReadFile(realPath)
79 2
	if err != nil {
80 2
		return nil, err
81 1
	}
82 2
	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 2
func (fs *FilesystemLoader) Path(name string) (string, error) {
91 2
	if filepath.IsAbs(name) {
92 0
		return name, nil
93 0
	}
94

95
	// root := fs.root
96 2
	if fs.root == "" {
97 2
		root, err := os.Getwd()
98 2
		if err != nil {
99 0
			return "", err
100 0
		}
101 2
		return filepath.Join(root, name), nil
102 2
	} else {
103 2
		return filepath.Join(fs.root, name), nil
104 1
	}
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 0
func NewSandboxedFilesystemLoader(root string) (*SandboxedFilesystemLoader, error) {
131 0
	fs, err := NewFileSystemLoader(root)
132 0
	if err != nil {
133 0
		return nil, err
134 0
	}
135 0
	return &SandboxedFilesystemLoader{
136 0
		FilesystemLoader: fs,
137 0
	}, 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
*/

Read our documentation on viewing source code .

Loading