Replacing {{string}} within php file - php

I'm including a file in one of my class methods, and in that file has html + php code. I return a string in that code. I explicitly wrote {{newsletter}} and then in my method I did the following:
$contactStr = include 'templates/contact.php';
$contactStr = str_replace("{{newsletter}}",$newsletterStr,$contactStr);
However, it's not replacing the string. The only reason I'm doing this is because when I try to pass the variable to the included file it doesn't seem to recognize it.
$newsletterStr = 'some value';
$contactStr = include 'templates/contact.php';
So, how do I implement the string replacement method?

You can use PHP as template engine. No need for {{newsletter}} constructs.
Say you output a variable $newsletter in your template file.
// templates/contact.php
<?= htmlspecialchars($newsletter, ENT_QUOTES); ?>
To replace the variables do the following:
$newsletter = 'Your content to replace';
ob_start();
include('templates/contact.php');
$contactStr = ob_get_clean();
echo $contactStr;
// $newsletter should be replaces by `Your content to replace`
In this way you can build your own template engine.
class Template
{
protected $_file;
protected $_data = array();
public function __construct($file = null)
{
$this->_file = $file;
}
public function set($key, $value)
{
$this->_data[$key] = $value;
return $this;
}
public function render()
{
extract($this->_data);
ob_start();
include($this->_file);
return ob_get_clean();
}
}
// use it
$template = new Template('templates/contact.php');
$template->set('newsletter', 'Your content to replace');
echo $template->render();
The best thing about it: You can use conditional statements and loops (full PHP) in your template right away.
Use this for better readability: https://www.php.net/manual/en/control-structures.alternative-syntax.php

This is a code i'm using for templating, should do the trick
if (preg_match_all("/{{(.*?)}}/", $template, $m)) {
foreach ($m[1] as $i => $varname) {
$template = str_replace($m[0][$i], sprintf('%s', $varname), $template);
}
}

maybe a bit late, but I was looking something like this.
The problem is that include does not return the file content, and easier solution could be to use file_get_contents function.
$template = file_get_contents('test.html', FILE_USE_INCLUDE_PATH);
$page = str_replace("{{nombre}}","Alvaro",$template);
echo $page;

based on #da-hype
<?php
$template = "hello {{name}} world! {{abc}}\n";
$data = ['name' => 'php', 'abc' => 'asodhausdhasudh'];
if (preg_match_all("/{{(.*?)}}/", $template, $m)) {
foreach ($m[1] as $i => $varname) {
$template = str_replace($m[0][$i], sprintf('%s', $data[$varname]), $template);
}
}
echo $template;
?>

Use output_buffers together with PHP-variables. It's far more secure, compatible and reusable.
function template($file, $vars=array()) {
if(file_exists($file)){
// Make variables from the array easily accessible in the view
extract($vars);
// Start collecting output in a buffer
ob_start();
require($file);
// Get the contents of the buffer
$applied_template = ob_get_contents();
// Flush the buffer
ob_end_clean();
return $applied_template;
}
}
$final_newsletter = template('letter.php', array('newsletter'=>'The letter...'));

<?php
//First, define in the template/body the same field names coming from your data source:
$body = "{{greeting}}, {{name}}! Are You {{age}} years old?";
//So fetch the data at the source (here we will create some data to simulate a data source)
$data_source['name'] = 'Philip';
$data_source['age'] = 35;
$data_source['greeting'] = 'hello';
//Replace with field name
foreach ($data_source as $field => $value) {
//$body = str_replace("{{" . $field . "}}", $value, $body);
$body = str_replace("{{{$field}}}", $value, $body);
}
echo $body; //hello, Philip! Are You 35 years old?
Note - An alternative way to do the substitution is to use the commented syntax.
But why does using the three square brackets work?
By default the square brackets allow you to insert a variable inside a string.
As in:
$name = 'James';
echo "His name is {$name}";
So when you use three square brackets around your variable, the innermost square bracket is dedicated to the interpolation of the variables, to display their values:
This {{{$field}}} turns into this {{field}}
Finally the replacement with str_replace function works for two square brackets.

no, don't include for this. include is executing php code. and it's return value is the value the included file returns - or if there is no return: 1.
What you want is file_get_contents():
// Here it is safe to use eval(), but it IS NOT a good practice.
$contactStr = file_get_contents('templates/contact.php');
eval(str_replace("{{newsletter}}", $newsletterStr, $contactStr));

Related

Make PHPBB 3.0.14 and ABBC3 compatible with PHP 7.3

I'm trying to make ABBC3 work with PHP 7.3 and PHPBB 3.0.14 since I can't move to PHPBB 3.3 due lots of issues with MODs not ported to extensions and theme (Absolution).
I have asked help in PHPBB forum without luck because 3.0.x and 3.1.x version are not supported anymore.
So after dozens of hours trying to understand bbcode functions I'm almost ready.
My code works when there's a single bbcode in message. But doesn't works when there's more bbcode or it's mixed with texts.
So I would like to get some help to solve this part to make everything work.
In line 98 in includes/bbcode.php this function:
$message = preg_replace($preg['search'], $preg['replace'], $message);
Is returning something like this:
$message = "some text $this->Text_effect_pass('glow', 'red', 'abc') another text. $this->moderator_pass('"fernando"', 'hello!') more text"
For this message:
some text [glow=red]abc[/glow] another text.
[mod="fernando"]hello![/mod] more text
The input for preg_replace above is like this just for context:
"some text [glow=red:mkpanc3g]abc[/glow:mkpanc3g] another text. [mod="fernando":mkpanc3g]hello![/mod:mkpanc3g]"
So basically I have to split this string in valid expressions to apply eval() then concatenate everything. Like this:
$message = "some text". eval($this->Text_effect_pass('glow', 'red', 'abc');) . "another text " . eval($this->moderator_pass('"fernando"', 'hello!');). "more text"
In this specific case there's also double quotes left in '"fernando"'.
I know is not safe apply eval() to user input so I would like to make some type of preg_match and/or preg_split to get values inside of () to pass as parameter to my functions.
The functions are basically:
Text_effect_pass()
moderator_pass()
anchor_pass()
simpleTabs_pass()
I'm thinking in something like this (Please ignore errors here):
if(preg_match("/$this->Text_effect_pass/", $message)
{
then split the string and get value inside of() and remove extra single or double quotes.
after:
$textEffect = Text_effect_pass($value[0], $value[1], $value[2]);
Finally concatenate everything:
$message = $string[0] .$textEffect. $string[1];
}
if(preg_match("/$this->moderator_pass/", $message)
{
.....
}
P.S.: ABBC3 is not compatible with PHP 7.3 due usage of e modifier. I have edited everything to remove the modifier.
Here you can see it working separately:
bbcode 1
bbcode 2
Can someone give me some help please?
After long time searching for a solution for this problem I found this site that helped me build the regex.
Now I have managed to solve the problem and I have my forum fully working with PHPBB 3.14, PHP 7.3 and ABBC3.
My solution is:
// Start Text_effect_pass
$regex = "/(\\$)(this->Text_effect_pass)(\().*?(\')(,)( )(\').*?(\')(,)( )(\').*?(\'\))/is";
if (preg_match_all($regex, $message, $matches)) {
foreach ($matches[0] as $key => $func) {
$bracket = preg_split("/(\\$)(this->Text_effect_pass)/", $func);
$param = explode("', '", $bracket[1]);
$param[0] = substr($param[0], 2);
$param[2] = substr($param[2], 0, strrpos($param[2], "')"));
$effect = $this->Text_effect_pass($param[0], $param[1], $param[2]);
if ($key == 0) {
$init = $message;
} else {
$init = $mess;
}
$mess = str_replace($matches[0][$key], $effect, $init);
}
$message = $mess;
} // End Text_effect_pass
// Start moderator_pass
$regex = "/(\\$)(this->moderator_pass)(\().*?(\')(,).*?(\').*?(\'\))/is";
if (preg_match_all($regex, $message, $matches)) {
foreach ($matches[0] as $key => $func) {
$bracket = "/(\\$)(this->moderator_pass)/";
$bracket = preg_split($bracket, $func);
$param = explode("', '", $bracket[1]);
$param[0] = substr($param[0], 2);
$param[1] = substr($param[1], 0, strrpos($param[1], "')"));
$effect = $this->moderator_pass($param[0], $param[1]);
if ($key == 0) {
$init = $message;
} else {
$init = $mess;
}
$mess = str_replace($matches[0][$key], $effect, $init);
}
$message = $mess;
} // End moderator_pass
If someone is interested can find patch files and instructions here.
Best regards.

PHP 7.2 - How to create anonymous function dynamically when having function body in a string

How do I create an anonymous function dynamically when I have function body in a string.
For e.g.
$user = "John Doe";
$body = "echo 'Hello' . $user;";
$myFunct = function($user) {$body}; // How do I have function body here from string.
$myFunct($user);
Any help would be much appreciated.
P.S.
I'm looking for a replacement for create_function() functionality which was there in prior versions of PHP. Just like in create_function() where we could pass the function body as a string, I would like to define anonymous function's body off the string variable.
If you have explored all other options and are absolutely sure the only way to accomplish your goals is to define custom functions at runtime using code that's in a string, you have two alternatives to using create_function.
The quick solution is to just use eval:
function create_custom_function($arguments, $body) {
return eval("return function($arguments) { $body };");
}
$myFunct = create_custom_function('$user', 'echo "Hello " . $user;');
$myFunct('John Doe');
// Hello John Doe
However, eval() can be disabled. If you need this sort of functionality even on servers where eval is not available, you can use the poor man's eval: write the function to a temporary file and then include it:
function create_custom_function($arguments, $body) {
$tmp_file = tempnam(sys_get_temp_dir(), "ccf");
file_put_contents($tmp_file, "<?php return function($arguments) { $body };");
$function = include($tmp_file);
unlink($tmp_file);
return $function;
}
$myFunct = create_custom_function('$user', 'echo "Hello " . $user;');
$myFunct('John Doe');
// Hello John Doe
In all honesty though, I strongly recommend against these approaches and suggest you find some other way to accomplish your goal. If you're building a custom code obfuscator, you're probably better off creating a php extension where the code is de-obfuscated prior to execution, similar to how ionCube Loader and Zend Guard Loader work.
You can use the callable type hint. Here is an example
function callThatAnonFunction(callable $callback) {
return $callback();
}
It can take an anonymous function with any arg params:
$user = "person";
$location = "world";
callThatAnonFunction(function() use ($user, $location) {
echo "Hello " . $user . " in " . $location;
});
You can try this:
$user = "John Doe";
$body = "echo 'Hello' . $user;";
$myFunct = function($user) {
return $body;
};
echo $myFunct($user);
Well this is ugly and you shouldn't really do this, but you said in a comment that you're doing this for a code obfuscator so here are my 2 cents:
$args = '$user, $number';
$body = 'echo "#$number: Hello $user.\n";';
function _create_function_without_eval($args, $body) {
$func_name = sprintf('temp_func_%s', md5($body));
$code = sprintf("<?php if (!function_exists('%s')) {function %s(%s){%s}}", $func_name, $func_name, $args, $body);
$func_file = tempnam('/tmp', $func_name);
$handle = fopen($func_file, "w+");
fwrite($handle, $code);
fclose($handle);
include $func_file;
unlink($func_file);
return function(...$user_args) use ($func_name) {
return call_user_func_array($func_name, $user_args);
};
}
function _create_function_with_eval($args, $body) {
$func_name = sprintf('temp_func_%s', md5($body));
$code = sprintf("if (!function_exists('%s')) {function %s(%s){%s}}", $func_name, $func_name, $args, $body);
eval($code);
return function(...$user_args) use ($func_name) {
return call_user_func_array($func_name, $user_args);
};
}
$fn_deprecated = create_function($args, $body);
$fn_with_eval = _create_function_with_eval($args, $body);
$fn_without_eval = _create_function_without_eval($args, $body);
echo $fn_deprecated('Old Bob', '1');
echo $fn_without_eval('Bob without eval', 2);
echo $fn_with_eval('Bob with eval', 3);
See it live here: https://3v4l.org/urQ4k
Caution
The eval() language construct is very dangerous because it allows execution of arbitrary PHP code. Its use thus is discouraged. If you have carefully verified that there is no other option than to use this construct, pay special attention not to pass any user provided data into it without properly validating it beforehand.
so Eval is the worst replacement, create_function is depreicated because of using eval.
use anonymous functions for adiinviter pro.
$b = function () use ($d,$f1,$c,$ps){
return gzinflate( base64_decode(str_rot13($ps) ) );
};
PHP developers love you hahaha look here
$user = "John Doe";
$body = 'echo "Hello " . $a;';
$f = create_function('$a', $body);
$f($user);
//out : Hello John Doe
Documentation PHP official : create_function(string $args,string $code)

PHP include HTML and echo out variable

I am working on a script with templates. So I have this PHP code:
<?php
$string = "TEST";
echo(file_get_contents('themes/default/test.html'));
?>
And I have this HTML (the test.html file):
<html>
<p>{$string}</p>
</html>
How can I make PHP actually display the variable inside the curly brackets? At the moment it displays {$string}.
P.S:
The string might also be an object with many many variables, and I will display them like that: {$object->variable}.
P.S 2: The HTML must stay as it is. This works:
$string = "I'm working!"
echo("The string is {$string}");
I need to use the same principle to display the value.
You can use the following code to achieve the desired result:
<?php
$string = "TEST";
$doc = file_get_contents('themes/default/test.html'));
echo preg_replace('/\{([A-Z]+)\}/', "$$1", $doc);
?>
P.S. Please note that it will assume that every string wrapped in { }
has a variable defined. So No error checking is implemented in the code above. furthermore it assumes that all variables have only alpha characters.
If it is possible to save your replacees in an array instead of normal variables you could use code below. I'm using it with a similar use case.
function loadFile($path) {
$vars = array();
$vars['string'] = "value";
$patterns = array_map("maskPattern", array_keys($vars));
$result = str_replace($patterns, $vars, file_get_contents($path));
return $result;
}
function maskPattern($value) {
return "{$" . $value . "}";
}
All you PHP must be in a <?php ?> block like this:
<html>
<p><?php echo "{" . $string . "}";?></p>
</html>
If you know the variable to replace in the html you can use the PHP function 'str_replace'. For your script,
$string = "TEST";
$content = file_get_contents('test.html');
$content = str_replace('{$string}', $string, $content);
echo($content);
It's simple to use echo.
<html>
<p>{<?php echo $string;?>}</p>
</html>
UPDATE 1:
After reading so many comments, found a solution, try this:
$string = "TEST";
$template = file_get_contents('themes/default/test.html', FILE_USE_INCLUDE_PATH);
$page = str_replace('{$string}',$string,$template);
echo $page;

Basic Template Engine Fix

I am attempting to make a (very) basic template engine for php. Based on my research I have found that a method that I am using is strongly disliked. I was wondering if anyone knew a great alternative to get the same result so I am not using it. And if anyone sees any other improvements that can be made please share!
the method that is not advised is the eval() method!
Here is the php file
<?php
class Engine {
private $vars = array();
public function assign($key, $value) {
$this->vars[$key] = $value;
}
public function render($file_name) {
$path = $file_name . '.html';
if (file_exists($path)) {
$content = file_get_contents($path);
foreach ($this->vars as $key => $value) {
$content = preg_replace('/\{' . $key . '\}/', $value, $content);
}
eval(' ?>' . $content . '<?php ');
} else {
exit('<h4>Engine Error</h4>');
}
}
}
?>
here is the index.php file
<?php
include_once 'engine.php';
$engine = new Engine;
$engine->assign('username', 'Zach');
$engine->assign('age', 21);
$engine->render('test');
?>
and here is just a test html file to display its basic function
My name is {username} and I am {age} years old!
outputs:
My name is Zach and I am 21 years old!
Many thanks in advance!
If you just want to output some text to the page, just use echo:
echo $content;
This is better than eval('?>' . $content . '<?php') for quite a few reasons: for one, if someone types in <?php phpinfo(); ?>, for example, as their username, it won't execute that code.
I would, however, note that you have some other problems. What if I do this?
$engine = new Engine;
$engine->assign('username', '{age}');
$engine->assign('age', 21);
$engine->render('test');
The {age} in the username value will be replaced with 21. Usually you don't want replacements to be replaced like that, particularly as it's order-dependent (if you assigned username later, it wouldn't happen).

Why won't this work in PHP?

$constPrefix = '_CONST_';
if (strstr($content, $constPrefix)) {
$constants = array('PHP_VERSION', '__FILE__');
foreach($constants as $constant) {
$constantOutput = eval($constant);
$content = str_replace($constPrefix . $constant, $constantOutput, $content);
}
}
Basically, just trying to parse some content and replace strings inside with the equivalent PHP constant. Is eval() what I should be using here? I've never actually found a reason to use it before, and it's almost 1am, and am wondering if that is a coincidence?
You can replace eval with constant:
$constantOutput = constant($constant);
Why don't you just leave out the eval?
<?php
$v = PHP_VERSION;
$f = __FILE__;
echo $v.' '.$f;
?>
gives
/tmp% php test.php
5.2.10-2ubuntu6.4 /tmp/test.php

Categories