How to print code generated by some function in php? - php

I have a code in my CMS that prints content:<?php print $content ?>
I would like to output the actual php and html code behind $content, ideally in the browser. What I mean here is not the result in the browser, but the actual code behind it.Is it possible at all?
EDIT: Just to explain further: I need to print the source code of $content. Basically this variable produce some html and php content. I would like to see the code it produces, change it and replace $content with my custom code. Ideally the source code should be printed in the browser, is there anny php function that does it?

First off install the Devel Module, it has a wonderful function called dpm() which will print the contents of any variable to the Drupal messages area.
Then you need to go into your theme's template.php file and implement hook_preprocess_page():
function mytheme_preprocess_page(&$vars) {
dpm($vars['content']);
}
That will print out the $content array before it's rendered into a string. In the same preprocess function you can also change $vars['content'] as you see fit, and the changes will be reflected in $content in page.tpl.php.
Hope that helps

What do you mean by 'the code'? I think what you want to do is not possible, unless you make some kind of quine it's not possible to output the actual php code of a php file when you run it.
If $content is something like:
$content = 3 + 4 + 5;
echo $content; will output 12 yes? But I'm taking it you want to output 3 + 4 + 5 or something along those lines. The thing is, PHP (although it doesn't feel like it) is compiled. In this trivial example, 3 + 4 + 5 is stored exactly nowhere in your compiled program, it is stored as 12 (since it's static). More complex lines of code will be stored as pointers, values etc., all in nicely obfuscated machine code. Getting back to the 3 + 4 + 5 requires reading the input file and outputting the relevant line, which is difficult (think about what happens if you add or remove some lines, or how your running program knows where in the source file it is, or even if it's in the right source file).
tl;dr: this is not possible.

Well, if you just want to see html source for $content, you should simply use htmlspecialchars :
echo htmlspecialchars($content);
http://php.net/htmlspecialchars
or http://php.net/htmlentities

Related

PHP code from a file does not execute

I am working on a BB code system for a content manager and I want to be able to use something like [code=php]<?php echo "Hello World!"; ?>[/code] in my textarea. Using GeSHi (A syntax highlighter) I have made the following function to parse the code:
function parsecode($codetype) {
$source = file_get_contents("file.php");
$language = $codetype;
$geshi = new GeSHi($source, $language);
echo '<code class="num">', implode(range(1,count(file("file.php"))), "<br />"), "</code>";
echo $geshi->parse_code();
}
This works perfectly fine!
Now this is where the BB code comes in. Using preg_replace I made a simple system that finds and replaces bits of code:
$find = array(
"/\[code\=(.+?)\](.+?)\[\/code\]/is"
);
$replace = array(
'<?php parsecode("$1"); ?>'
);
Yes, for now this means it only reads the language and parses the file "file.php" but eventually I will have this work different, but that's not important for now.
What happens, is that the BB code gets executed correctly, and the result is that it does in fact execute the code, but it does NOT execute the function parsecode() . I made a small adjustment to find out where the problem is, and made it save to a file and it turns out the file contained the following: <?php parsecode("php"); ?> . Which is exactly what it should contain. When I write this line of code in the file, it executes.
Anything submitted in the textarea gets stored in a file, which is then read using fopen() and then echo'd on a different page.
My question: Why does the function not execute & parse the code like it should?
Thanks ahead!
There is only one way to get PHP code to execute within PHP code (change code dynamically) and that is with eval().
http://www.php.net/manual/en/function.eval.php
This let's you dynamically make code and execute it
Please remember this quote though:
"If eval() is the answer, you're almost certainly asking the wrong question. -- Rasmus Lerdorf, BDFL of PHP"
eval() is known for security vulnerabilities and being exploited. Highly not recommended.
However, as long as you're not using user generated code IN the eval you will be fine. You could put a return around it to get the result only in the database.
You could instead achieve the same effect by running this in the script but not replacing it before it's run in the entry but on the forum page itself...

Alternative to php preg_match to pull data from an external website?

I want to extrat the content of a specific div in an external webpage, the div looks like this:
<dt>Win rate</dt><dd><div>50%</div></dd>
My target is the "50%". I'm actually using this php code to extract the content:
function getvalue($parameter,$content){
preg_match($parameter, $content, $match);
return $match[1];
};
$parameter = '#<dt>Score</dt><dd><div>(.*)</div></dd>#';
$content = file_get_contents('https://somewebpage.com');
Everything works fine, the problem is that this method is taking too much time, especially if I've to use it several times with diferents $content.
I would like to know if there's a better (faster, simplier, etc.) way to acomplish the same function? Thx!
You may use DOMDocument::loadHTML and navigate your way to the given node.
$content = file_get_contents('https://somewebpage.com');
$doc = new DOMDocument();
$doc->loadHTML($content);
Now to get to the desired node, you may use method DOMDocument::getElementsByTagName, e.g.
$dds = $doc->getElementsByTagName('dd');
foreach($dds as $dd) {
// process each <dd> element here, extract inner div and its inner html...
}
Edit: I see a point #pebbl has made about DomDocument being slower. Indeed it is, however, parsing HTML with preg_match is a call for trouble; In that case, I'd also recommend looking at event-driven SAX XML parser. It is much more lightweight, faster and less memory intensive as it does not build a tree. You may take a look at XML_HTMLSax for such a parser.
There are basically three main things you can do to improve the speed of your code:
Off load the external page load to another time (i.e. use cron)
On a linux based server I would know what to suggest but seeing as you use Windows I'm not sure what the equivalent would be, but Cron for linux allows you to fire off scripts at certain schedule time offsets - in the background - so not using a browser. Basically I would recommend that you create a script who's sole purpose is to go and fetch the website pages at a particular time offset (depending on how frequently you need to update your data) and then write those webpages to files on your local system.
$listOfSites = array(
'http://www.something.com/page.htm',
'http://www.something-else.co.uk/index.php',
);
$dirToContainSites = getcwd() . '/sites';
foreach ( $listOfSites as $site ) {
$content = file_get_contents( $site );
/// i've just simply converted the URL into a filename here, there are
/// better ways of handling this, but this at least keeps things simple.
/// the following just converts any non letter or non number into an
/// underscore... so, http___www_something_com_page_htm
$file_name = preg_replace('/[^a-z0-9]/i','_', $site);
file_put_contents( $dirToContainSites . '/' . $file_name, $content );
}
Once you've created this script, you then need to set the server up to execute it as regularly as you need. Then you can modify your front-end script that displays the stats to read from local files, this would give a significant speed increase.
You can find out how to read files from a directory here:
http://uk.php.net/manual/en/function.dir.php
Or the simpler method (but prone to possible problems) is just to re-step your array of sites, convert the URLs to file names using the preg_replace above, and then check for the file's existence in the folder.
Cache the result of calculating your statistics
It's quite likely this being a stats page that you'll want to visit it quite frequently (not as frequent as a public page, but still). If the same page is visited more often than the cron-based script is executed then there is no reason to do all the calculation again. So basically all you have to do to cache your output is do something similar to the following:
$cachedVersion = getcwd() . '/cached/stats.html';
/// check to see if there is a cached version of this page
if ( file_exists($cachedVersion) ) {
/// if so, load it and echo it to the browser
echo file_get_contents($cachedVersion);
}
else {
/// start output buffering so we can catch what we send to the browser
ob_start();
/// DO YOUR STATS CALCULATION HERE AND ECHO IT TO THE BROWSER LIKE NORMAL
/// end output buffering and grab the contents so we now have a string
/// of the page we've just generated
$content = ob_get_contents(); ob_end_clean();
/// write the content to the cached file for next time
file_put_contents($cachedVersion, $content);
echo $content;
}
Once you start caching things you need to be aware of when you should delete or clear your cache - otherwise if you don't your stats output will never change. With regards to this situation, the best time to clear your cache is at the point you go and fetch the external web pages again. So you should add this line to the bottom of your "cron" script.
$cachedVersion = getcwd() . '/cached/stats.html';
unlink( $cachedVersion ); /// will delete the file
There are other speed improvements you could make to the caching system (you could even record the modified times of the external webpages and load only when they have been updated) but I've tried to keep things easy to explain.
Don't use a HTML Parser for this situation
Scanning a HTML file for one particular unique value does not require the use of a fully-blown or even lightweight HTML Parser. Using RegExp incorrectly seems to be one of those things that lots of start-up programmers fall into, and is a question that is always asked. This has led to lots of automatic knee-jerk reactions from more experience coders to automatically adhere to the following logic:
if ( $askedAboutUsingRegExpForHTML ) {
$automatically->orderTheSillyPersonToUse( $HTMLParser );
} else {
$soundAdvice = $think->about( $theSituation );
print $soundAdvice;
}
HTMLParsers should be used when the target within the markup is not so unique, or your pattern to match relies on such flimsy rules that it'll break the second an extra tag or character occurs. They should be used to make your code more reliable, not if you want to speed things up. Even parsers that do not build a tree of all the elements will still be using some form of string searching or regular expression notation, so unless the library-code you are using has been compiled in an extremely optimised manner, it will not beat well coded strpos/preg_match logic.
Considering I have not seen the HTML you are hoping to parse, I could be way off, but from what I've seen of your snippet it should be quite easy to find the value using a combination of strpos and preg_match. Obviously if your HTML is more complex and might have random multiple occurances of <dt>Win rate</dt><dd><div>50%</div></dd> it will cause problems - but even so - a HTMLParser would still have the same problem.
$offset = 0;
/// loop through the occurances of 'Win rate'
while ( ($p = stripos ($html, 'win rate', $offset)) !== FALSE ) {
/// grab out a snippet of the surrounding HTML to speed up the RegExp
$snippet = substr($html, $p, $p + 50 );
/// I've extended your RegExp to try and account for 'white space' that could
/// occur around the elements. The following wont take in to account any random
/// attributes that may appear, so if you find some pages aren't working - echo
/// out the $snippet var using something like "echo '<xmp>'.$snippet.'</xmp>';"
/// and that should show you what is appearing that is breaking the RegExp.
if ( preg_match('#^win\s+rate\s*</dt>\s*<dd>\s*<div>\s*([0-9]+%)\s*<#i', $snippet, $regs) ) {
/// once you are here your % value will be in $regs[1];
break; /// exit the while loop as we have found our 'Win rate'
}
/// reset our offset for the next loop
$offset = $p;
}
Gotchas to be aware of
If you are new to PHP, as you state in a comment above, then the above may seem rather complicated - which it is. What you are trying to do is quite complex, especially if you want to do it optimally and fast. However, if you follow throught the code I've given and research any bits that you aren't sure of / haven't heard of (php.net is your friend), it should give you a better understanding of a good way to achieve what you are doing.
Guessing ahead however, here are some of the problems you might face with the above:
File Permission errors - in order to be able to read and write files to and from the local operating system you will need to have the correct permissions to do so. If you find you can not write files to a particular directory it might be that the host you are using wont allow you to do so. If this is the case you can either contact them to ask about how to get write permission to a folder, or if that isn't possible you can easily change the code above to use a database instead.
I can't see my content - when using output buffering all the echo and print commands do not get sent to the browser, they instead get saved up in memory. PHP should automatically output all the stored content when the script exits, but if you use a command like ob_end_clean() this actually wipes the 'buffer' so all the content is erased. This can lead to confusing situations when you know you are echoing something.. but it just isn't appearing.
(Mini Disclaimer :) I've typed all the above manually so you may find there are PHP errors, if so, and they are baffling, just write them back here and StackOverflow can help you out)
Instead of trying to not use preg_match why not just trim your document contents down in size? for example, you could dump everything before <body and everything after </body>. then preg_match will be searching less content already.
Also, you could try to do each one of these processes as a pseudo separate thread, so that way they aren't happening one at a time.

var reads HTML code as STRING

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.

Is there a php function for using the source code of another web page?

I want to create a PHP script that grabs the content of a website. So let's say it grabs all the source code for that website and I say which lines of code I need.
Is there a function in PHP that allows you too do this or is it impossible?
Disclaimer: I'm not going to use this for any illegal purposes at all and not asking you too write any code, just tell me if its possible and if you can how I'd go about doing it. Also I'm just asking in general, not for any specific reason. Thanks! :)
file('http://the.url.com') returns an array of lines from a url.
so for the 24th line do this:
$lines = file('http://www.whatever.com');
echo $lines[23];
This sounds like a horrible idea, but here we go:
Use file_get_contents() to get the file. You cannot get the source if the web server first processes it, so you may need to use an extension like .txt. Unless you password protect the file, obviously anybody can get it.
Use explode() with the \n delimiter to split the source code into lines.
Use array_slice() to get the lines you need.
eval() the code.
Note: if you just want the HTML output, then ignore the bit about the source in step 1 and obviously you can skip the whole eval() thing.

how to eval() a segment of a string

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.

Categories