I'm writing a script (in PHP) which will go through a PHP file, find all instances of a function, replace the function name with another name, and manipulate the parameters. I'm using get_file_contents() then strpos() to find the positions of the function, but I'm trying to find a good way to extract the parameters once I know the position of the start of the function. Right now I'm just using loop which walks through the next characters in the file string and counts the number of opening and closing parentheses. Once it closes the function parameters it quits and passes back the string of parameters. Unfortunately, runs into trouble with quotes enclosing parentheses (i.e. function_name(')', 3)). I could just count quotes too, but then I have to deal with escaped quotes, different types of quotes, etc.
Is there a good way to, knowing the start of the function, to grab the string of parameters reliably? Thank you much!
EDIT:
In case i didn't read the question carefully, if you want to only get function parameters,you can see these example :
$content_file = 'function func_name($param_1=\'\',$param_2=\'\'){';
preg_match('/function func_name\((.*)\{/',$content_file,$match_case);
print_r($match_case);
but if you want to manipulate the function, read below.
How about these :
read file using file_get_contents();
use preg_match_all(); to get all function inside that file.
please not that i write /*[new_function]*/ inside that file to identify EOF.
I use this to dynamically add/ delete function without have to open that php files.
Practically, it should be like this :
//I use codeigniter read_file(); function to read the file.
//$content_file = read_file('path_to/some_php_file.php');
//i dont know whether these line below will work.
$content_file = file_get_content('path_to/some_php_file.php');
//get all function inside php file.
preg_match_all('/function (.*)\(/',$content_file,$match_case);
//
//function name u want to get
$search_f_name = 'some_function_name';
//
for($i=0;$i<count($match_case[1]);$i++){
if(trim($match_case[1][$i]) == $search_f_name){
break;
}
}
//get end position by using next function start position
if($i!=count($match_case[1])-1){
$next_function= $match_case[1][$i+1];
$get_end_pos = strripos($content_file,'function '.$next_function);
} else {
//Please not that i write /*[new_function]*/ at the end of my php file
//before php closing tag ( ?> ) to identify EOF.
$get_end_pos = strripos($content_file,'/*[new_function]*/');
}
//get start position
$get_pos = strripos($content_file,'function '.$search_f_name);
//get function string
$func_string = substr($content_file,$get_pos,$get_end_pos-$get_pos);
you can do echo $func_string; to know whether these code is running well or not.
Use a real parser, like this one:
https://github.com/nikic/PHP-Parser
Using this library, you can manipulate the source code as a tree of "node" objects, rather than as a string, and write it back out.
Related
I'm building an ExpressionEngine module in PHP.
In ExpressionEngine, one can access parameters passed to the module in a template using:
$my_param = $this->EE->TMPL->fetch_param('my_param');
However, when I fetch a string that way, explode does not work on it:
public function get_tyres()
{
$tyres = $this->EE->TMPL->fetch_param('tyres');
echo($tyres);
// this shows: '205/55R16M+S|205/55R16|205/55R16'
// now I want to split it into single tyres, using the pipe as a delimiter
$tyre_array = explode("|", $tyres);
foreach($tyre_array as $tyre)
{
echo($tyre . '<br>');
}
// the above produces: '205/55R16M+S|205/55R16|205/55R16',
// where I'd expect it to produce:
// 205/55R16M+S
// 205/55R16
// 205/55R16
}
I've tried to specifically cast to a string using $tyres = (string) $this->EE->TMPL->fetch_param('tyres');, with no luck.
I've also tried manually creating and exploding a string:
$tyres = '205/55R16M+S|205/55R16|205/55R16'; which worked, but obviously I need to get the param from the template, not hard code it.
Lastly, I tried using preg_split and a regex, with no luck either:
$tyre_array = preg_split('/\|/', $tyres); which also returned an array with the entire string in it.
What could be at work here? Is this a scope related thing? Is it an encoding-related thing? What to look for next?
Update
Okay, we're getting somewhere. I've added the following to the function:
for($i = 0; $i < strlen($tyres); $i++) {
echo substr($tyres, $i, 1) . ", ";
}
Which returns... {, v, e, r, s, i, o, n, :, t, y, r, e, s, }, and that is in fact the variable passed to PHP in the HTML template:
{exp:my_module:tyres tyres="{version:tyres}"}
<h1>{tyre:name}</h1>
... more irrelevant HTML
{/exp:my_module:tyres}
This means it has something to do with the parsing order of ExpressionEngine. Apparently, the variable {version:tyres} isn't parsed yet. So I pass that variable to the module, it tries to explode it by the pipe character, but the string {version:tyres} does not contain a pipe, meaning it can't be exploded. ExpressionEngine then returns {version:tyres} as a whole, passes it back in to the template and then the variable is parsed as 205/55R16M+S|205/55R16|205/55R16.
I've tested this, and can confirm that exploding by ':' returns the array:
array (size=2)
0 => string '{version' (length=8)
1 => string 'tyres}' (length=6)
I will now look in to ExpressionEngine parse order. If anyone has an idea on how to work around this, I'd be happy to know ;-).
I tested your code, copy and pasting your test string, and it works fine for me. Make sure your pipe ("|") is really the character you think it is, and not, say, some crazy unicode stuff that just looks like a pipe, but is actually Klingon for for 'staff', or something.
Try something like this as a reality check:
echo " the pipe is at " .strpos($tyres,"|"). " and I really hope this it says '12'";
The answer lies in the ExpressionEngine parse order, as outlined here: https://ellislab.com/expressionengine/user-guide/templates/template_engine.html#rendering-stages
Because the template tag {exp:my_module:tyres} used a variable passed to it by a template tag that it was nested in, the variable wasn't parsed yet as the innermost tags are parsed first.
Adding the parameter parse="inward" to the outer template tag makes ExpressionEngine parse that tag first, passing the correct variable to the inner template tag.
See https://ellislab.com/expressionengine/user-guide/templates/plugins.html#changing-parsing-order for more on changing the parsing order.
Okay so I have my PHP code: (I need help with the 4th line) More info down below the code.
Basicly I am trying to get code below. i am trying to put get part of url but it doesn;'t work
$oIMDB = new IMDB('<?ph p echo$_GET("m");?> ')
and on the 4th line i put the code
and the code doesn't work, how can i use it?
I think you mean this:
$oIMDB = new IMDB($_GET["m"]);
you shouldn't need the php scripting block inside the class call. Function parameters don't need quotes either unless you are using a literal string. Try
$oIMDB = new IMDB($_GET["m"])
Let's say I have a file "English.txt" containing these lines :
$_LANG["accountinfo"] = "Account Information";
$_LANG["accountstats"] = "Account Statistics";
Note : the file extension is .txt and there is nothing I can do to change that. There is no opening PHP tag (<?php) or anything, just those lines, period.
I need to extract and actually get the $_LANG array declared from these lines. How do I do that? Simply includeing the file echoes every line, so I do
ob_start();
include '/path/to/English.txt';
$str = ob_get_clean();
Now, if I call eval on that string, I get an syntax error, unexpected $end. Any ideas?
Thanks.
eval(file_get_contents('English.txt'));
however, be sure NOBODY can change English.txt, it could be dangerous!
First of all, note that you should use file_get_contents instead of include with output buffering. Since it contains no <?php tag, there is no need to run it through the script processor.
The following works perfectly in my tests:
<?php
$contents = file_get_contents("English.txt");
eval($contents);
var_dump($_LANG);
As one of the comments said, if you do the above and still get an error, then your file does NOT contain exactly/only those lines. Make sure the file is actually syntax compliant.
As has been mentioned, you should really use eval only as a last resort, and only if the file is as safe to execute as any code you write. In other words, it must not be editable by the outside world.
Very simply, i want to make a variable reads the html code as string ,, i mean dont execute it (run it) .
the problem with the code is : i have a html file , and i want to get the content of it , and make some preg_replace for it (run a function on the html code), the problem is i cant use preg_replace, or any another function because the html code is executed by php (php reads the html code)..
i wish you understand me, i want something like highlight_string, but it save the html code in the variable.
Thank you.
you're probably trying to include or require the HTML code.
which is incorrect since it is evaluated as part of the source.
instead, use a function such as file_get_contents() to read the file into a string.
Use file_get_contents() as #David Chan suggested and then pass the result through htmlentities()... it converts the characters to HTML entities (i.e., < to <).
$getTheContent = file_get_contents($filepath);
echo htmlentities($getTheContent);
It should return the code, not executed.
I have a string that has HTML & PHP in it, when I pull the string from the database, it is echo'd to screen, but the PHP code doesn't display. The string looks like this:
$string = 'Hello <?php echo 'World';?>';
echo $string;
Output
Hello
Source Code
Hello <?php echo 'World';?>
When I look in the source code, I can see the php line there. So what I need to do is eval() just the php segment that is in the string.
One thing to consider is that the PHP could be located anywhere in the string at any given time.
* Just to clarify, my PHP config is correct, this is a case of some PHP being dumped from the database and not rendering, because I am echo'ing a variable with the PHP code in it, it fails to run. *
Thanks again for any help I may receive.
$str = "Hello
<?php echo 'World';?>";
$matches = array();
preg_match('/<\?php (.+) \?>/x', $str, $matches);
eval($matches[1]);
This will work, but like others have and will suggest, this is a terrible idea. Your application architecture should never revolve around storing code in the database.
Most simply, if you have pages that always need to display strings, store those strings in the database, not code to produce them. Real world data is more complicated than this, but must always be properly modelled in the database.
Edit: Would need adapting with preg_replace_callback to remove the source/interpolate correctly.
You shouldn't eval the php code, just run it. It's need to be php interpreter installed, and apache+php properly configured. Then this .php file should output Hello World.
Answer to the edit:
Use preg_replace_callback to get the php part, eval it, replace the input to the output, then echo it.
But. If you should eval things come from database, i'm almost sure, it's a design error.
eval() should work fine, as long as the code is proper PHP and ends with a semicolon. How about you strip off the php tag first, then eval it.
The following example was tested and works:
<?php
$db_result = "<?php echo 'World';?>";
$stripped_code = str_replace('?>', '', str_replace('<?php', '', $db_result));
eval($stripped_code);
?>
Just make sure that whatever you retrieve from the db has been properly sanitized first, since you're essentially allowing anyone who can get content into the db, to execute code.