View previous topic :: View next topic |
Author |
Message |
sm@rty Smarty Regular
Joined: 01 Oct 2014 Posts: 65
|
Posted: Fri Feb 13, 2015 6:27 pm Post subject: eval smarty code is good way ? |
|
|
hi
my users cant include any template.
but i using this way :
Code: |
{*file1.tpl
this file is in database
*}
{$a = 1}
|
and main template code :
Code: |
{$b = 2}
{*_require is define*}
{eval _require('file1.tpl')}
{$a*$b}
|
is good ? (not problem security || performance) |
|
Back to top |
|
AnrDaemon Administrator
Joined: 03 Dec 2012 Posts: 1785
|
Posted: Sat Feb 14, 2015 6:02 am Post subject: |
|
|
php.ini
disabled_functions "eval"
Now go ahead and eval() anything you like.
(If that was not clear enough: eval() by itself is a security threat. Go back to reading the documentation, it explains how to pull templates from different sources.) |
|
Back to top |
|
U.Tews Administrator
Joined: 22 Nov 2006 Posts: 5068 Location: Hamburg / Germany
|
Posted: Sat Feb 14, 2015 1:48 pm Post subject: |
|
|
The Smarty {eval} tag requires that the parameter does return the template source. Does your function _require() do that?
Also {eval} does have bad performance as very time the page is called the compiler will be called.
In the demo folder you will find an example of a database plugin resource.mysql.php.
Implementing a resource plugin would have the best performance.
AnrDaemon wrote:
Quote: | php.ini
disabled_functions "eval"
Now go ahead and eval() anything you like.
(If that was not clear enough: eval() by itself is a security threat. Go back to reading the documentation, it explains how to pull templates from different sources.) |
The Smarty {eval} tag is not the same thing as PHP eval.
The template code is execude under same security restrictions as any other template file.[/b] |
|
Back to top |
|
sm@rty Smarty Regular
Joined: 01 Oct 2014 Posts: 65
|
Posted: Sat Feb 14, 2015 3:19 pm Post subject: |
|
|
Quote: | The Smarty {eval} tag requires that the parameter does return the template source. Does your function _require() do that? |
yes
Quote: | Also {eval} does have bad performance as very time the page is called the compiler will be called.
|
so i not using this feature.
my goal :
smarty code(for example) :
Code: |
{my_private_require_name_block 'name_of_tpl_in_db_for_current_user'}
|
php function(for example) :
Code: |
function my_private_require_name_block($tpl_name){
if($r=$mysql->result("SELECT `content` FROM `smarty_templates` WHERE `user_id` = 'user_id' && 'name' = '%n'",array('%n' => $name)))
return $r;
throw new Exception('cant not found '.$tpl_name.' on line ?');
}
|
this is my goal |
|
Back to top |
|
U.Tews Administrator
Joined: 22 Nov 2006 Posts: 5068 Location: Hamburg / Germany
|
Posted: Sat Feb 14, 2015 8:36 pm Post subject: |
|
|
Copy file resource.mysql.php from the demo folder into the plugins folder.
In the comment of the file you see the table structure we used for the example.
Field 'name' is the template name.
Field 'source' is the content template source.
Field 'modified' is a timestamp which is automatically updated by mysql.
You may add your 'user_id' field.
Edit __construct() with the access data of your database and table and
Code: |
$this->fetch = $this->db->prepare('SELECT modified, source FROM templates WHERE name = :name && user_id = :user_id');
$this->mtime = $this->db->prepare('SELECT modified FROM templates WHERE name = :name && user_id = :user_id');
|
Now we need to pass the user_id as global variable to the resource plugin.
Modify the 2 lines containing execute() to
Code: | $this->fetch->execute(array('name' => $name, 'user_id' => $GLOBALS[ 'user_id']));
and
$this->mtime->execute(array('name' => $name, 'user_id' => $GLOBALS[ 'user_id']));
|
In the template you can now include the subtemplate from mysql
Code: |
{include file='mysql:file1.tpl' compile_id = $smarty.globals.user_id}
|
NOTE we use the user_id as compile_id because your database table may contain for different users templates with same name. With the compile _id Smarty keeps compiled templates separated.
By using the mysql resource Smarty will save the compiled template code for later reuse like on normal template files.
The template gets automatically recompiled if it was modified in the database.
You will have same performance as file subtemplates. |
|
Back to top |
|
sm@rty Smarty Regular
Joined: 01 Oct 2014 Posts: 65
|
Posted: Sun Feb 15, 2015 8:19 am Post subject: |
|
|
very thank
but 3 problem !!!!
first problem :
include disabled by security setting ! but i enable this
this not dangerous ?
second problem :
Quote: | {include file='mysql:file1.tpl' compile_id = $smarty.globals.user_id} |
compile_id set by user ! it be dangerous !
but i find and fix this problem (only for me):
in file smarty_internal_compile_include.php after line 117 :
Code: |
##################
#
$_attr['compile_id'] = $GLOBALS['user_id'];
#
################## |
no problem security?
third problem !!!! :
after enable caching and in first compile i view this error :
###
filemtime(): stat failed for .../inc/classes/smarty/data/compile/20^62b6b9659f4c8e2b5b605661d8b6ebe023698bb0_0.mysql.page1.php ....inc\classes\smarty\sysplugins\smarty_template_compiled.php 133
###
/inc/classes/smarty/data/ is true |
|
Back to top |
|
AnrDaemon Administrator
Joined: 03 Dec 2012 Posts: 1785
|
Posted: Sun Feb 15, 2015 5:25 pm Post subject: |
|
|
compile_id is safe.
You must create ALL directories before using them. |
|
Back to top |
|
U.Tews Administrator
Joined: 22 Nov 2006 Posts: 5068 Location: Hamburg / Germany
|
Posted: Sun Feb 15, 2015 6:58 pm Post subject: |
|
|
Do not modify smarty_internal_compile_include.php.
It can besolved with an additional plugin.
Create in the plugins folder file function.my_private_require_name_block.php
Code: | function smarty_function_my_private_require_name_block($params, $template)
{
return $template->smarty->fetch("mysql:{$params['file']}", null, $GLOBALS['user_id'], $template);
} |
In the template
Code: |
{my_private_require_name_block file='foo.tpl'}
|
If you enable caching you must call display() with a cache_id to keep also the cache files separated by user
Code: | $smarty->display('main.tpl', $GLOBALS['user_id']); |
For the third problem mute expected errors in your main PHP script
Code: | Smarty::muteExpectedErrors(); |
|
|
Back to top |
|
sm@rty Smarty Regular
Joined: 01 Oct 2014 Posts: 65
|
Posted: Sun Feb 15, 2015 10:13 pm Post subject: |
|
|
thanks
ok but this is not main goal !!!!!!
main goal is simulate of include in addition to top security !
Quote: |
It can besolved with an additional plugin.
Create in the plugins folder file function.my_private_require_name_block.php |
ok your way is very good but there is not relation between current template and fetch template !
for example :
page1 :
in main page :
Code: |
{myFuncPlug file="page1"}
{$a}
|
after run main page and after include page1; $a cant not echo in main page !(php error Notice: Undefined index: a in)
but one way be worked !!!
page1 :
in main page :
Code: |
{$a = 'smarty'}
{myFuncPlug file="page1"}
|
after run main page and after include page1 $a in page 1 echo smarty.
why ?
--------------------------------------------------
Quote: | For the third problem mute expected errors in your main PHP script
Code:
Smarty::muteExpectedErrors(); |
not be work !
i using this code :
Code: | set_error_handler(function(){}); | [/code] |
|
Back to top |
|
U.Tews Administrator
Joined: 22 Nov 2006 Posts: 5068 Location: Hamburg / Germany
|
|
Back to top |
|
sm@rty Smarty Regular
Joined: 01 Oct 2014 Posts: 65
|
Posted: Mon Feb 16, 2015 8:27 am Post subject: |
|
|
thanks very much.
smarty has powerful support.
also thanks to AnrDaemon for reply. |
|
Back to top |
|
U.Tews Administrator
Joined: 22 Nov 2006 Posts: 5068 Location: Hamburg / Germany
|
Posted: Mon Feb 16, 2015 9:14 pm Post subject: |
|
|
Here is a better solution which will run the included sub template in same context (scope) as the calling template.
So you will no longer need the scope=parent.
In plugins folder file compiler.include_block.php Code: |
class Smarty_Compiler_Include_Block extends Smarty_Internal_Compile_Include
{
public $required_attributes = array('file');
public $shorttag_order = array('file');
public $option_flags = array('nocache', 'inline', 'caching');
public $optional_attributes = array('compile_id', 'scope');
public function compile($args, Smarty_Internal_SmartyTemplateCompiler $compiler, $parameter = null)
{
$_attr = $this->getAttributes($compiler, $args);
$file = trim($args[0]['file'], "'\"");
$args[0]['file'] = "'mysql:$file'";
$args[]['compile_id'] = "'{$GLOBALS['user_id']}'";
$args[]['scope'] = "'parent'";
return parent::compile($args, $compiler, $parameter);
}
}
|
Main page:
Code: | {include_block 'file1.tpl'} |
Page 1:
|
|
Back to top |
|
sm@rty Smarty Regular
Joined: 01 Oct 2014 Posts: 65
|
Posted: Tue Feb 17, 2015 8:02 pm Post subject: |
|
|
yes this is better solution and this was my goal.
thanks |
|
Back to top |
|
sm@rty Smarty Regular
Joined: 01 Oct 2014 Posts: 65
|
Posted: Sun Mar 08, 2015 1:13 pm Post subject: |
|
|
i find a bug in your plugin !
if use a variable in your plugin , not working :
example :
Code: | {require file=$config.pages.virtual.css1} |
php syntax error
Code: | PHP Parse error: syntax error, unexpected 'config' (T_STRING |
smarty php output in compile dir :
Code: | <?php echo $_smarty_tpl->getSubTemplate ('mysql:((string)$_smarty_tpl->tpl_vars['config']->value).".pages.virtual.css1', $_smarty_tpl->cache_id, '5', 0, $_smarty_tpl->cache_lifetime, array(), 1);
?> |
|
|
Back to top |
|
sm@rty Smarty Regular
Joined: 01 Oct 2014 Posts: 65
|
Posted: Mon Mar 09, 2015 7:38 am Post subject: |
|
|
I've resolved
Code: |
$_attr = $this->getAttributes($compiler, $args);
$newArgs = array();
$newArgs[0]['file'] = "'mysql:'.".$_attr['file'];
$newArgs[]['compile_id'] = "'{$GLOBALS['user_id']}'";
$newArgs[]['scope'] = "'parent'";
return parent::compile($newArgs, $compiler, $parameter);
|
|
|
Back to top |
|
|