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