|
1 <?php |
|
2 /** |
|
3 * Smarty Internal Plugin Resource File |
|
4 * |
|
5 * @package Smarty |
|
6 * @subpackage TemplateResources |
|
7 * @author Uwe Tews |
|
8 * @author Rodney Rehm |
|
9 */ |
|
10 |
|
11 /** |
|
12 * Smarty Internal Plugin Resource File |
|
13 * Implements the file system as resource for Smarty templates |
|
14 * |
|
15 * @package Smarty |
|
16 * @subpackage TemplateResources |
|
17 */ |
|
18 class Smarty_Internal_Resource_File extends Smarty_Resource { |
|
19 /** |
|
20 * build template filepath by traversing the template_dir array |
|
21 * |
|
22 * @param Smarty_Template_Source $source source object |
|
23 * @param Smarty_Internal_Template $_template template object |
|
24 * |
|
25 * @return string fully qualified filepath |
|
26 * @throws SmartyException |
|
27 */ |
|
28 protected function buildFilepath(Smarty_Template_Source $source, Smarty_Internal_Template $_template = null) { |
|
29 $file = $source->name; |
|
30 preg_match('#^(?P<absolute>[\\\/]|[a-zA-Z]:[\\\/])|(\[(?P<index>[^\]]+)\])|(?P<rel>\.[\\\/])#', $file, $fileMatch); |
|
31 // save basename |
|
32 if (!empty($fileMatch['absolute'])) { |
|
33 $file = $this->normalizePath($file); |
|
34 return is_file($file) ? $file : false; |
|
35 } |
|
36 // go relative to a given template? |
|
37 if (!empty($fileMatch['rel']) && $_template && $_template->parent instanceof Smarty_Internal_Template) { |
|
38 if ($_template->parent->source->type != 'file' && $_template->parent->source->type != 'extends' && !$_template->parent->allow_relative_path) { |
|
39 throw new SmartyException("Template '{$file}' cannot be relative to template of resource type '{$_template->parent->source->type}'"); |
|
40 } |
|
41 $path = dirname($_template->parent->source->filepath) . DS . $file; |
|
42 // normalize path |
|
43 $path = $this->normalizePath($path); |
|
44 // files relative to a template only get one shot |
|
45 return is_file($path) ? $path : false; |
|
46 } |
|
47 |
|
48 if ($source->isConfig) { |
|
49 $_directories = $source->smarty->getConfigDir(); |
|
50 } else { |
|
51 $_directories = $source->smarty->getTemplateDir(); |
|
52 } |
|
53 // template_dir index? |
|
54 if (!empty($fileMatch['index'])) { |
|
55 $index = $fileMatch['index']; |
|
56 $_directory = null; |
|
57 // try string indexes |
|
58 if (isset($_directories[$index])) { |
|
59 $_directory = $_directories[$index]; |
|
60 } elseif (is_numeric($index)) { |
|
61 // try numeric index |
|
62 $index = (int)$index; |
|
63 if (isset($_directories[$index])) { |
|
64 $_directory = $_directories[$index]; |
|
65 } else { |
|
66 // try at location index |
|
67 $keys = array_keys($_directories); |
|
68 $_directory = $_directories[$keys[$index]]; |
|
69 } |
|
70 } |
|
71 if ($_directory) { |
|
72 preg_match('#\](.+)$#', $file, $fileMatch); |
|
73 $path = $_directory . $fileMatch[1]; |
|
74 $path = $this->normalizePath($path); |
|
75 if (is_file($path)) { |
|
76 return $path; |
|
77 } |
|
78 } else { |
|
79 // index not found |
|
80 return false; |
|
81 } |
|
82 } |
|
83 |
|
84 // relative file name? |
|
85 foreach ($_directories as $_directory) { |
|
86 $_filepath = $_directory . $file; |
|
87 $path = $this->normalizePath($_filepath); |
|
88 if (is_file($path)) { |
|
89 return $path; |
|
90 } |
|
91 if ($source->smarty->use_include_path && !preg_match('/^([\/\\\\]|[a-zA-Z]:[\/\\\\])/', $_directory)) { |
|
92 // try PHP include_path |
|
93 if (function_exists('stream_resolve_include_path')) { |
|
94 $_filepath = stream_resolve_include_path($_filepath); |
|
95 } else { |
|
96 $_filepath = Smarty_Internal_Get_Include_Path::getIncludePath($_filepath); |
|
97 } |
|
98 if ($_filepath !== false) { |
|
99 $path = $this->normalizePath($_filepath); |
|
100 if (is_file($path)) { |
|
101 return $path; |
|
102 } |
|
103 } |
|
104 } |
|
105 } |
|
106 // Could be relative to cwd |
|
107 $path = $this->normalizePath(getcwd() . DS . $file); |
|
108 return is_file($path) ? $path : false; |
|
109 } |
|
110 |
|
111 /** |
|
112 * Normalize path |
|
113 * - remove /./ and /../ |
|
114 * - make it absolute |
|
115 * |
|
116 * @param string $path file path |
|
117 * |
|
118 * @return string |
|
119 */ |
|
120 public function normalizePath($path) { |
|
121 if ($path[0] == '.') { |
|
122 $path = getcwd() . DS . $path; |
|
123 } |
|
124 $path = preg_replace('#[\\\/]+([.][\\\/]+)*#', DS, $path); |
|
125 while (strrpos($path, '.' . DS) !== false) { |
|
126 $path = preg_replace('#([\\\/]([^\\\/]+[\\\/]){2}([.][.][\\\/]){2})|([\\\/][^\\\/]+[\\\/][.][.][\\\/])#', DS, $path); |
|
127 } |
|
128 return $path; |
|
129 } |
|
130 |
|
131 /** |
|
132 * test is file exists and save timestamp |
|
133 * |
|
134 * @param Smarty_Template_Source $source source object |
|
135 * @param string $file file name |
|
136 * |
|
137 * @return bool true if file exists |
|
138 */ |
|
139 protected function fileExists(Smarty_Template_Source $source, $file) { |
|
140 $source->timestamp = is_file($file) ? @filemtime($file) : false; |
|
141 return $source->exists = !!$source->timestamp; |
|
142 } |
|
143 |
|
144 /** |
|
145 * populate Source Object with meta data from Resource |
|
146 * |
|
147 * @param Smarty_Template_Source $source source object |
|
148 * @param Smarty_Internal_Template $_template template object |
|
149 */ |
|
150 public function populate(Smarty_Template_Source $source, Smarty_Internal_Template $_template = null) { |
|
151 $source->filepath = $this->buildFilepath($source, $_template); |
|
152 |
|
153 if ($source->filepath !== false) { |
|
154 if (is_object($source->smarty->security_policy)) { |
|
155 $source->smarty->security_policy->isTrustedResourceDir($source->filepath); |
|
156 } |
|
157 $source->exists = true; |
|
158 $source->uid = sha1($source->filepath); |
|
159 if ($source->smarty->compile_check && !isset($source->timestamp)) { |
|
160 $source->timestamp = @filemtime($source->filepath); |
|
161 } |
|
162 } else { |
|
163 $source->timestamp = false; |
|
164 $source->exists = false; |
|
165 } |
|
166 } |
|
167 |
|
168 /** |
|
169 * populate Source Object with timestamp and exists from Resource |
|
170 * |
|
171 * @param Smarty_Template_Source $source source object |
|
172 */ |
|
173 public function populateTimestamp(Smarty_Template_Source $source) { |
|
174 $source->timestamp = $source->exists = is_file($source->filepath); |
|
175 if ($source->exists) { |
|
176 $source->timestamp = @filemtime($source->filepath); |
|
177 } |
|
178 } |
|
179 |
|
180 /** |
|
181 * Load template's source from file into current template object |
|
182 * |
|
183 * @param Smarty_Template_Source $source source object |
|
184 * |
|
185 * @return string template source |
|
186 * @throws SmartyException if source cannot be loaded |
|
187 */ |
|
188 public function getContent(Smarty_Template_Source $source) { |
|
189 if ($source->timestamp) { |
|
190 return file_get_contents($source->filepath); |
|
191 } |
|
192 if ($source instanceof Smarty_Config_Source) { |
|
193 throw new SmartyException("Unable to read config {$source->type} '{$source->name}'"); |
|
194 } |
|
195 throw new SmartyException("Unable to read template {$source->type} '{$source->name}'"); |
|
196 } |
|
197 |
|
198 /** |
|
199 * Determine basename for compiled filename |
|
200 * |
|
201 * @param Smarty_Template_Source $source source object |
|
202 * |
|
203 * @return string resource's basename |
|
204 */ |
|
205 public function getBasename(Smarty_Template_Source $source) { |
|
206 return basename($source->filepath); |
|
207 } |
|
208 } |