What's __halt_compiler in PHP for? - php

From the manual:
void __halt_compiler ( void )
This function halts the execution of the compiler. This can be useful to embed data in PHP scripts, like the installation files.
Note: __halt_compiler() can only be used from the outermost scope.
Can anyone provide an actually case where this function is useful?

Assume you have one script with some php code and lots and lots of binary clutter.
<?php doStuff(); __halt_compliler(); [BIG_BINARY_MESS]
then you want the compiler to NOT try to parse the binary because if there is <? somewhere in the binary it would break.
The point is being able to just ship one file with binary data and php code.
For a little example see this blog post
So you want not only to stop the execution of a script (like exit() would) but to stop the parsing so that you can have "invalid syntax" at the end of file and php still can execute the first part.
Another example:
This will get parsed as valid php and execute just fine:
<?php $a = 1; echo $a; __halt_compiler(); §RW$FG$%ZDS$TSG$TSZ%U(); §$"§%"§$!!();
To access the data:
<?php
$file = fopen(__FILE__, 'rb');
// Go to the end of the __halt_compiler();
fseek($file, __COMPILER_HALT_OFFSET__);
echo stream_get_contents($file);
__halt_compiler(); §RW$FG$%ZDS$TSG$TSZ%U(); §$"§%"§$!!();
This will output §RW$FG$%ZDS$TSG$TSZ%U(); §$"§%"§$!!();

Previously, The ClassGenerator in the PhpSpec unit testing library provided a good example of using __halt_compiler(), which the PHP class contains a code template for a PHP class.
They've recently update to read the template from a seperate file, but initially the getTemplate() method will attempt to read the PHP code template provided in the file that follows the __halt_compiler() call. This avoids the <?php token from getting parsed.
/**
* The Class Generator is responsible for generating the classes from a resource
* in the appropriate folder using the template provided
*/
class ClassGenerator
{
//...
/**
* #return string
*/
protected function getTemplate()
{
return file_get_contents(__FILE__, null, null, __COMPILER_HALT_OFFSET__);
}
}
__halt_compiler();<?php%namespace_block%
class %name%
{
}

Here's another possible use. I have a long file of PHP functions. Many of these aren't currently valid, but might be required soon. I want to disable them, but not entirely delete them. I want the code to remain visible to all developers so that they can reinstate the code if they need it. Also anyone searching via grep would still find the code.
So I move the code to the end of the file, and want to "comment it out". However the functions themselves have comments in. So I would need to start a new block comment after the end of each block comment in the original code. __halt_compiler(); does the job without changing any other lines.
(If I delete the code and commit that to a version control system, that does allow me to reinstate the code, but it wouldn't be visible to other developers unless they new to look.)

Related

Server-sent events in PHP (without echo or print)

We have built a prototype application in PHP and JS using Server-Sent Events (single AJAX requests, multiple streamed events sent by event handlers in PHP). Essentially the PHP at some point is using echo to send data back, much like this example: https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events/Using_server-sent_events#sending_events_from_the_server i.e.
echo "event: ping\n";
However the platform we are building for (Magento) has strict coding standards that prohibit echo and print (and print_r and var_dump). Is there any way around this aside from scrapping SSE and setting up AJAX polling?
Well, I think you have 2 ways of "echoing" something in Magento.
1. Adding your PHP file to /pub
Yes, you can run you custom PHP file to "echo" whatever you want.
But you will need to place it under <magento folder>/pub/yourfile.php.
If you're using nginx you will also need to create an exception for your file. Otherwise, Magento's routing will be used.
For doing that, find something like location ~ ^/(index|get|static|errors/report|errors/404|errors/503|health_check)\.php$ { in your nginx file, and add yourfile.php there.
For example:
location ~ ^/(index|get|static|errors/report|errors/404|errors/503|health_check|yourfile)\.php$ {.
Once your file is there, it will be served under yourstore.com/yourfile.php or yourstore.com/pub/yourfile.php (in case you are wrongfully exposing the root directory).
2. The magento way - create a controller
You will need to create a module and a controller.
There are plenty of tutorials out there explaining how to create them.
Here you can find how to create the basic module's structure.
And in this other article you can see how to create different controllers with different types of return.
Magento does have strict standards as part of there PHPCS configuration that need to be adhered to before they will allow you publish a module to there market, there is not Solid fix for the issue you have mentioned regarding using echo or print in a magneto file as part of your module. however we have found a work around by leveraging phps Output Buffering.
We have successfully submitted a module using the below mentioned function and example.
You can use ob_start() and ob_end_flush() it behaves similar to how a print or echo would when interacting with the event stream. See link below for example.
Why?
The ob_flush() function outputs the contents of the topmost output buffer and then clears the buffer of the contents. The output may be caught by another output buffer or, if there are no other output buffers, sent directly to the browser ( IE. your currently open stream ).
Example:
/**
* Send Data
*
* #param string $content
*/
function sseEchoAlternative(string $content)
{
ob_start(function () use ($content) { //Expect a warning here
return $content;
});
ob_end_flush();
}
Ref: ServerSentEvents.php

How to know if a script was included inside another script

I am new to PHP and very likely I am using the incorrect approach because I am not used to think like a PHP programmer.
I have some files that include other files as dependencies, these files need to have global code that will be executed if $_POST contains certain values, something like this
if (isset($_POST["SomeValue"]))
{
/* code goes here */
}
All the files will contain this code section, each one it's own code of course.
The problem is that since the files can be included in another one of these files, then the code section I describe is executed in every included file, even when I post trhough AJAX and explicitly use the URL of the script I want to POST to.
I tried using the $_SERVER array to try and guess which script was used for the post request, and even though it worked because it was the right script, it was the same script for every included file.
Question is:
Is there a way to know if the file was included into another file so I can test for that and skip the code that only execute if $_POST contains the required values?
Note: The files are generated using a python script which itself uses a c library that scans a database for it's tables and constraints, the c library is mine as well as the python script, they work very well and if there is a fix for a single file, obviously it only needs to be performed to the python script.
I tell the reader (potential answerer) about this because I think it makes it clear that I don't need a solution that works over the already existant files, because they can be re-generated.
From the sounds of it you could make some improvements on your code structure to completely avoid this problem. However, with the information given a simple flag variable should do the trick:
if (!isset($postCodeExecuted) && isset($_POST["SomeValue"]))
{
/* code goes here */
$postCodeExecuted = true;
}
This variable will be set in the global namespace and therefore it will be available from everywhere.
I solved the problem by doing this
$caller = str_replace($_SERVER["DOCUMENT_ROOT"], "", __FILE__);
if ($_SERVER["REQUEST_METHOD"] === "POST" and $caller === $_SERVER["PHP_SELF"])
performThisAction();

Is eval() functionally the same as include in PHP, given the following example?

I am working within an existing PHP program that has an established way that it dynamically loads certain PHP files for rendering HTML, by doing something basically this:
try {
$includeFilePath = realpath($mySubPath);
include $includeFilePath;
} catch (Exception $e) {
//imagine code that handles error
}
Assume that both file to be included and the file containing the above method are read-only and it's not permissible to alter these actual files on disk. However the above method may be overridden by extending the class it is part of. Meanwhile the file that's being included cannot be overridden gracefully because it does not contain classes, just a mix of PHP and HTML instructions (old school "phtml").
Now what I want to do instead is:
try {
$includeFilePath = realpath($mySubPath);
$codeToModify = substr(file_get_contents($includeFilePath),5);
$codeToEval = $this->modifyCode($codeToModify);
eval($codeToExecute);
} catch (Exception $e) {
//imagine code that handles error
}
... where the modifyCode($str) method is defined elsewhere, and basically what it would do is (a) check the existing file against a pre-known hash checksum value to ensure it has not been modified, and (b) inject known safe code into it in order to add additional functionality to the application (it's "known safe" because we also would use a similar hash verification system on it and validate it).
Now my question is, assuming that security risks are not a concern here, is there any functional reason why eval would be problematic?
Note: no files we'd be including have closing html tags, only opening ones. I chose to use substr($str,5) to trim the opening tag as opposed to adding opening and closing tags as I've seen done elsewhere; that ought to work, right?
Explanation:
Since I anticipate a lot of you might wonder, "Why would you want to do that?", the reason is fairly complicated, but I'll try to explain it. The alternative to doing the above would be to include an entirely different file: one that already contains the custom code I want to use on top of the code from the base file. However the custom code I want to use is all additional code not present in the original base file, so we would end up with a fair amount of duplicated code instead of a more elegant solution where only the new code is "injected" into the base code prior to execution. Even still, using a new file that contains both the old and new code would technically work fine for now.
The problem is, though, in the future it's entirely possible that when we upgrade the base program, there will be changes to the original file (the one that's been effectively overridden by using my custom version of it). If that happens, our override would continue to rely on the previous version's code for that file, since the part of it that carried over from the original base system would no longer match up with the new version's normal default code for that file.
So, to address that problem, I want to go with the method of injecting the code using my custom modifyCode($str) method. That method can tell if there's been any updates to the original file (whether due to a hacker or due to system update) and it would be able to then warn the admin to check out why this code has changed, and issue an approval before executing the modified version of the code by updating the checksum with the hash of the new version of the file to be overridden. That way we can safely update the system and know it will fall back on the default behavior of the new version of the system rather than continue to run old code (which risks breaking the system) or adding mods intended for old versions of the code to new versions of the code that they haven't yet been tested on.
I hope that makes sense.
No. Call stack would be changed (error messages, magic constant __FILE__). Relative includes in evaled code could be broken. Two new variables $codeToModify, $codeToEval would appear in evaled code scope. Evaled code would not be cached. Parse error inside evaled code does not interrupt whole script. Eval could be disabled with Suhosin.

very interesting use of return keyword in php

as we know, return keyword will RETURN some value and exit current function. Mean, that this one used only inside some functions.
BUT, I saw some php-dev's use return keyword outside functions, even in index.php file (in root of web server). What is that mean???? By the way, maybe it's logical to require some file inside function, but this style isnt mine.
There's not much more to say than what the docs do.
About the common usage of return:
If called from within a function, the return statement immediately
ends execution of the current function, and returns its argument as
the value of the function call. return will also end the execution of
an eval() statement or script file.
About the less common usage:
If called from the global scope, then execution of the current script
file is ended. If the current script file was included or required,
then control is passed back to the calling file. Furthermore, if the
current script file was included, then the value given to return will
be returned as the value of the include call. If return is called from
within the main script file, then script execution ends. If the
current script file was named by the auto_prepend_file or
auto_append_file configuration options in php.ini, then that script
file's execution is ended.
Its documented somewhere within the manual
// myFile.php
return array( 'foo' => 'bar');
// somewhere else
$config = include 'myFile.php';
echo $config['foo'];
If you use return in the main scope php will leave the file inclusion and use the value as "return value" of the inclusion (include[_once](), require[_once]()).
BUT, I saw some php-dev's use return keyword outside functions, even
in index.php file (in root of web server). What is that mean???
You know the common purpose. But what you are asking is used to prevent code injection in php include files. Take a look at this post which explains it:
Prevent Code Injection in PHP include files
While discussing Coding Standards it was not long ago I argued against
adding ?> at the end of php files. But miqrogroove pointed to me an
interesting aspect why it actually can make sense to have it and an
additional return statement at the end of each file: That one (merely
the return statement) can prevent an attacker to append payload code
to existing PHP files, for example known include files. The
countermeasurement is pretty easy, just add a return statement at the
end of the file. It will end the include “subroutine”:
Example:
/* all the include file's php code */
return;
?>

Making Only Specific Functions and Variables Available in PHP

I want to make a programming environment. I will explain it with an example.
One programmer will write that code;
<html>
<head>
<?php definedMetaTags(); ?>
</head>
</body>
Programmer will save this file and then upload to my system. That file will be executed at server side and then they system will turn generated code back.
That definedMetaTags() function will be already written in the system.
An example of Compiler.php:
<?php
require_once("definitionsForProgrammer.php");
include("uploadedfile.php");
?>
My question is that I want to allow that uploadedfile.php only what functions I want. Else, maybe that programmer writes some codes what I want him/her to do. (Deleting files, mysql connection, etc.)
Is there any way to allow a code only specific functions, variables, constans?
If the goal is to allow a user to insert placeholders that will be replaced by some PHP function execution, then there's no need to treat the uploaded file as PHP code:
<html>
<head>
{[definedMetaTags]}
</head>
</body>
Then Compiler.php would look like this:
<?php
require_once("definitionsForProgrammer.php");
$macros = array();
$macros['definedMetaTags'] = definedMetaTags();
$output = file_get_contents("uploadedfile.php");
foreach($macros as $macro=>$value) $output = str_replace("{[$macro]}", $value, $output);
echo $output;
?>
The definedMetaTags() function would need to be reworked so that it returns the tags as a string instead of printing them directly to output.
This method would allow you to define any number of macros without exposing yourself to all the security risks the others here have mentioned.
If you're aiming for security and you want to let them to write functions, then the short answer is: no.
Essentially you're asking for a PHP sandbox which will let you constrain what code can be executed. PHP would have to support this at a fundamental level for it to work. For example, supposing you took the approach of saying "I only allow the user to write a function named 'foo'". Inside that function, though the user can do all kinds of bad things like making system calls, downloading other code and executing it, etc. In order to prevent this you'd need to implement checks at a much lower level in the system.
If you're willing to restrict the scope only to variable definitions then yes you can do it. You can use token_get_all() and token_name() to examine the file to make sure that it doesn't have any code that you don't want in it. For example:
foreach (token_get_all(file_get_contents("uploadedfile.php")) as $token) {
if (is_array($token)) {
echo token_name($token[0]), " ";
} else {
echo $token;
}
}
If you don't like any tokens you see, don't include the file. You could theoretically guard against bad functions this way as well, but it'll require a fair amount of effort to properly parse the file and make sure that they're not doing something bad.
references:
http://www.php.net/manual/en/function.token-get-all.php
http://www.php.net/manual/en/function.token-name.php
http://www.php.net/manual/en/tokens.php
Well, if i'm understanding your question correctly. If you include("uploadedfile.php"); you will acquire everything in it.
What you could do is break your code up into related sections (whether it be via classes or just function definitions in a file) then only include the file/class that you want.
(let me know if that's not what your asking)

Categories