Smarty Forum Index Smarty
WARNING: All discussion is moving to https://reddit.com/r/smarty, please go there! This forum will be closing soon.

eval smarty code is good way ?
Goto page 1, 2  Next
 
This forum is locked: you cannot post, reply to, or edit topics.   This topic is locked: you cannot edit posts or make replies.    Smarty Forum Index -> General
View previous topic :: View next topic  
Author Message
sm@rty
Smarty Regular


Joined: 01 Oct 2014
Posts: 65

PostPosted: Fri Feb 13, 2015 6:27 pm    Post subject: eval smarty code is good way ? Reply with quote

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
View user's profile Send private message
AnrDaemon
Administrator


Joined: 03 Dec 2012
Posts: 1785

PostPosted: Sat Feb 14, 2015 6:02 am    Post subject: Reply with 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.)
Back to top
View user's profile Send private message
U.Tews
Administrator


Joined: 22 Nov 2006
Posts: 5068
Location: Hamburg / Germany

PostPosted: Sat Feb 14, 2015 1:48 pm    Post subject: Reply with quote

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
View user's profile Send private message
sm@rty
Smarty Regular


Joined: 01 Oct 2014
Posts: 65

PostPosted: Sat Feb 14, 2015 3:19 pm    Post subject: Reply with quote

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
View user's profile Send private message
U.Tews
Administrator


Joined: 22 Nov 2006
Posts: 5068
Location: Hamburg / Germany

PostPosted: Sat Feb 14, 2015 8:36 pm    Post subject: Reply with quote

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
View user's profile Send private message
sm@rty
Smarty Regular


Joined: 01 Oct 2014
Posts: 65

PostPosted: Sun Feb 15, 2015 8:19 am    Post subject: Reply with quote

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
View user's profile Send private message
AnrDaemon
Administrator


Joined: 03 Dec 2012
Posts: 1785

PostPosted: Sun Feb 15, 2015 5:25 pm    Post subject: Reply with quote

compile_id is safe.
You must create ALL directories before using them.
Back to top
View user's profile Send private message
U.Tews
Administrator


Joined: 22 Nov 2006
Posts: 5068
Location: Hamburg / Germany

PostPosted: Sun Feb 15, 2015 6:58 pm    Post subject: Reply with quote

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
View user's profile Send private message
sm@rty
Smarty Regular


Joined: 01 Oct 2014
Posts: 65

PostPosted: Sun Feb 15, 2015 10:13 pm    Post subject: Reply with quote

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 :
Code:

{$a = 'smarty'}


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 :
Code:

{$a}


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
View user's profile Send private message
U.Tews
Administrator


Joined: 22 Nov 2006
Posts: 5068
Location: Hamburg / Germany

PostPosted: Sun Feb 15, 2015 10:44 pm    Post subject: Reply with quote

Templates run in their own isolated context same like a PHP subroutine.
Variables assigned in a subtemplate are normally not seen in the calling template.

But you can assign variables to the outer (parent) template scope


page1
Code:
{$a = 'smarty' scope=parent}

http://www.smarty.net/docs/en/language.builtin.functions.tpl#language.function.shortform.assign

Second
A custom error handler must be registered first.
Code:
set_error_handler(function(){});
Smarty::muteExpectedErrors();

http://www.smarty.net/docs/en/troubleshooting.tpl#smarty.php.errors
http://www.smarty.net/docs/en/api.mute.expected.errors.tpl
Back to top
View user's profile Send private message
sm@rty
Smarty Regular


Joined: 01 Oct 2014
Posts: 65

PostPosted: Mon Feb 16, 2015 8:27 am    Post subject: Reply with quote

thanks very much.

smarty has powerful support.

also thanks to AnrDaemon for reply.
Back to top
View user's profile Send private message
U.Tews
Administrator


Joined: 22 Nov 2006
Posts: 5068
Location: Hamburg / Germany

PostPosted: Mon Feb 16, 2015 9:14 pm    Post subject: Reply with quote

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:
Code:
{$a = 'smarty'}
Back to top
View user's profile Send private message
sm@rty
Smarty Regular


Joined: 01 Oct 2014
Posts: 65

PostPosted: Tue Feb 17, 2015 8:02 pm    Post subject: Reply with quote

yes this is better solution and this was my goal.

thanks
Back to top
View user's profile Send private message
sm@rty
Smarty Regular


Joined: 01 Oct 2014
Posts: 65

PostPosted: Sun Mar 08, 2015 1:13 pm    Post subject: Reply with quote

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
View user's profile Send private message
sm@rty
Smarty Regular


Joined: 01 Oct 2014
Posts: 65

PostPosted: Mon Mar 09, 2015 7:38 am    Post subject: Reply with quote

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
View user's profile Send private message
Display posts from previous:   
This forum is locked: you cannot post, reply to, or edit topics.   This topic is locked: you cannot edit posts or make replies.    Smarty Forum Index -> General All times are GMT
Goto page 1, 2  Next
Page 1 of 2

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group
Protected by Anti-Spam ACP