library/smarty/libs/sysplugins/smarty_internal_resource_file.php
changeset 46 f11c31f7fa3e
parent 45 a56e7f9a0463
child 47 03388ec805b4
equal deleted inserted replaced
45:a56e7f9a0463 46:f11c31f7fa3e
     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 }