I want to hook before execution / or replace standart core functions, for example i im going to prevent both include and require accesa to any scripts. Is any way to make it without any extra .dll's? Or another case is_array($myarr); i would be to hook at array($myarr) === $myarr; (looks like it is faster) to avoid creating extra classes and functions.
Ps and one more question : how to prevent all php execution after some moment? I have html templates with php parts <?=$myvar?> i want to prevent short sintax and execution at all when my script ends work, what i have to try?
About hooks to standart functions: there is no way to do that without external modules. APD PECL module
will do the job.
rename_function('require', 'internal_require'); // saving reference to original function
override_function('require', '$filename',
'print "require called"; internal_require($filename);');
Second question is not very clear. Do you want to hook on standart is_array function, to array() lexical construct or (array) type casting?
About stopping php interpretation: have a look at __halt_compiler function. But keep in mind that succeeding blocks of php will be just embedded in HTML (thus visible to everybody).
If you want to disable functions, you can use safe mode, but it is deprecated and not recommended. And as madfriend says, __halt_compiler just sends everything below it as text. Bear in mind that it can only be called from the outermost scope - I.e. not inside curly braces (if, loops, functions etc.)
Related
For a long time now, I have had my own wrapper function around echo, so that instead of:
echo 'This is an example.';
I do (in CLI scripts):
terminal_output('This is an example.');
This allows me to, for example, do fancy outputting of the text on the terminal. For example, I can make it look like it's "typed out" with random delays.
Sometimes, I realize that I have been using "echo" instead of my wrapper function, and then I have to sit and change them all into my function calls.
It strikes me that, maybe, there is some way to "hook into" the echo function so that I can indeed use echo everywhere, yet do any kind of fancy processing I feel like? And of course, that wrapper function would check whether it's in web or cli mode, and always directly output if in web mode.
I've oftentimes found hidden "gems" like this in PHP which are barely documented or well hidden, so maybe it's the case this time as well?
Functions can be namespaced. PHP native functions can be redefined with the same name in custom namespaces.
But echo is a special case. It is not a function, but is a language construct.
// echo supports non-function-shape calls since it's a language construct.
echo "string", "string";
AKAIK, the language may not allow you to define a function with that name.
I want to hook before execution / or replace standart core functions, for example i im going to prevent both include and require accesa to any scripts. Is any way to make it without any extra .dll's? Or another case is_array($myarr); i would be to hook at array($myarr) === $myarr; (looks like it is faster) to avoid creating extra classes and functions.
Ps and one more question : how to prevent all php execution after some moment? I have html templates with php parts <?=$myvar?> i want to prevent short sintax and execution at all when my script ends work, what i have to try?
About hooks to standart functions: there is no way to do that without external modules. APD PECL module
will do the job.
rename_function('require', 'internal_require'); // saving reference to original function
override_function('require', '$filename',
'print "require called"; internal_require($filename);');
Second question is not very clear. Do you want to hook on standart is_array function, to array() lexical construct or (array) type casting?
About stopping php interpretation: have a look at __halt_compiler function. But keep in mind that succeeding blocks of php will be just embedded in HTML (thus visible to everybody).
If you want to disable functions, you can use safe mode, but it is deprecated and not recommended. And as madfriend says, __halt_compiler just sends everything below it as text. Bear in mind that it can only be called from the outermost scope - I.e. not inside curly braces (if, loops, functions etc.)
I do not have control over the code I'm executing. This is a third party function, but not user-entered. These are things that are versioned so it is impractical that I poke there and change all die()'s into something more sane. Because a new version is coming from time to time and then I could paradoxically make the code even more insecure by trying mess with it poor error handling.
so let's say we have a function:
fuction myfunc() {
// lot's of complicated code
if (!is_file('myfile.txt') exit('file not found');
// and so on
}
What I'm trying to do is to somewhat run that piece of code and return to my main thread and then act accordingly with that error.
I've tried die() or eval() but this returns the whole script.
Bummer ?
A Hail Mary approach is to use runkit's runkit_function_redefine or function_override to redefine the functions die and exit to throw an Exception instead.
A potential problem is that the 3rd party can catch those exceptions and might not deal with them correctly. It's also very likely that you can't properly deal with the exception either.
You can use register_shutdown_function to run code after exit has been called. You are somewhat limited in what you can do at this point as some services have already been shut down (such as autoloading). I think you can still output content, not sure about sessions and other headers.
Another approach would be to run the code in a seperate php process (or http request), for instance by calling php through exec.
A more solid approach can be to add predicitions to your own code, ensuring the bad states are never reached when calling the 3rd party code. It is possible that not all preconditions can be met.
Ideally only code that is an entry point (like a router script) may exit. Using exit anywhere else is just shoddy programming really.
If you have not read Halcyon's answer, you should have a look at it first.
Since you mention eval(), I assume you have the code as a string. I will refer to both die() and exit() by just the latter, but things should be relevant for both.
You can try and replace occurrences of die() and exit() with something, and then eval. It's simple but that can be very messy.
One thing to look out for, IF you decide to do this, is that you may end up replacing occurrences which are not really 'code'. For example, echo "Let him exit()";.
Also, when you consider possible equivalent syntax, like exit (); , exit; or exit(1);, it gets much more unpleasant. You'll have to handle those with a regex.
But if you can safely assume that
those two signatures (die() and exit()) are the only ones you need to worry about; and
that strings (or other content) are not going to contain those 'phrases'
then you can use this approach.
I was reading up on Paul Bigger's http://blog.paulbiggar.com/archive/a-rant-about-php-compilers-in-general-and-hiphop-in-particular/ and he mentions that HPHP doesn't fully support dynamic constructs. He then states, "Still, a naive approach is to just stick a switch statement in, and compile everything that makes sense." Is he saying that instead of a dynamic include, you could use switch statements to include the proper file? If so, why would this work and why is it "easier" for a compiler to compile? As always, thx for your time!
from my understanding, if you've got this
include "$foo.php";
the compiler would have no clue what you're going to include. On the other side, with this
switch($foo) {
case 'bar' : include "bar.php";
case 'quux' : include "quux.php";
}
they can simply compile "bar" and "quux" and wrap them in an if statement which checks $foo and executes whatever is appropriate.
A compiler expects to be able to identify all of the source and binary files that might be used by the program being compiled.
include($random_file);
If the file named in $random_file declares constants, classes, variables, the compiler will have no way knowing because the value of $random_file is not known at compile time. Your code using those constants, classes and variables will fail in difficult-to-debug ways. The switch statement would make known the list of possible files so the compiler can discover any relevant declarations.
Languages designed to be compiled have dynamic linkers and foreign function interfaces that combine to provide similar functionality to include($random_file) without needing the explicit switch.
I'm looking to improve my PHP coding and am wondering what PHP-specific techniques other programmers use to improve productivity or workaround PHP limitations.
Some examples:
Class naming convention to handle namespaces: Part1_Part2_ClassName maps to file Part1/Part2/ClassName.php
if ( count($arrayName) ) // handles $arrayName being unset or empty
Variable function names, e.g. $func = 'foo'; $func($bar); // calls foo($bar);
Ultimately, you'll get the most out of PHP first by learning generally good programming practices, before focusing on anything PHP-specific. Having said that...
Apply liberally for fun and profit:
Iterators in foreach loops. There's almost never a wrong time.
Design around class autoloading. Use spl_autoload_register(), not __autoload(). For bonus points, have it scan a directory tree recursively, then feel free to reorganize your classes into a more logical directory structure.
Typehint everywhere. Use assertions for scalars.
function f(SomeClass $x, array $y, $z) {
assert(is_bool($z))
}
Output something other than HTML.
header('Content-type: text/xml'); // or text/css, application/pdf, or...
Learn to use exceptions. Write an error handler that converts errors into exceptions.
Replace your define() global constants with class constants.
Replace your Unix timestamps with a proper Date class.
In long functions, unset() variables when you're done with them.
Use with guilty pleasure:
Loop over an object's data members like an array. Feel guilty that they aren't declared private. This isn't some heathen language like Python or Lisp.
Use output buffers for assembling long strings.
ob_start();
echo "whatever\n";
debug_print_backtrace();
$s = ob_get_clean();
Avoid unless absolutely necessary, and probably not even then, unless you really hate maintenance programmers, and yourself:
Magic methods (__get, __set, __call)
extract()
Structured arrays -- use an object
My experience with PHP has taught me a few things. To name a few:
Always output errors. These are the first two lines of my typical project (in development mode):
ini_set('display_errors', '1');
error_reporting(E_ALL);
Never use automagic. Stuff like autoLoad may bite you in the future.
Always require dependent classes using require_once. That way you can be sure you'll have your dependencies straight.
Use if(isset($array[$key])) instead of if($array[$key]). The second will raise a warning if the key isn't defined.
When defining variables (even with for cycles) give them verbose names ($listIndex instead of $j)
Comment, comment, comment. If a particular snippet of code doesn't seem obvious, leave a comment. Later on you might need to review it and might not remember what it's purpose is.
Other than that, class, function and variable naming conventions are up to you and your team. Lately I've been using Zend Framework's naming conventions because they feel right to me.
Also, and when in development mode, I set an error handler that will output an error page at the slightest error (even warnings), giving me the full backtrace.
Fortunately, namespaces are in 5.3 and 6. I would highly recommend against using the Path_To_ClassName idiom. It makes messy code, and you can never change your library structure... ever.
The SPL's autoload is great. If you're organized, it can save you the typical 20-line block of includes and requires at the top of every file. You can also change things around in your code library, and as long as PHP can include from those directories, nothing breaks.
Make liberal use of === over ==. For instance:
if (array_search('needle',$array) == false) {
// it's not there, i think...
}
will give a false negative if 'needle' is at key zero. Instead:
if (array_search('needle',$array) === false) {
// it's not there!
}
will always be accurate.
See this question: Hidden Features of PHP. It has a lot of really useful PHP tips, the best of which have bubbled up to the top of the list.
There are a few things I do in PHP that tend to be PHP-specific.
Assemble strings with an array.
A lot of string manipulation is expensive in PHP, so I tend to write algorithms that reduce the discrete number of string manipulations I do. The classic example is building a string with a loop. Start with an array(), instead, and do array concatenation in the loop. Then implode() it at the end. (This also neatly solves the trailing-comma problem.)
Array constants are nifty for implementing named parameters to functions.
Enable NOTICE, and if you realy want to STRICT error reporting. It prevents a lot of errors and code smell: ini_set('display_errors', 1); error_reporting(E_ALL && $_STRICT);
Stay away from global variables
Keep as many functions as possible short. It reads easier, and is easy to maintain. Some people say that you should be able to see the whole function on your screen, or, at least, that the beginning and end curly brackets of loops and structures in the function should both be on your screen
Don't trust user input!
I've been developing with PHP (and MySQL) for the last 5 years. Most recently I started using a framework (Zend) with a solid javascript library (Dojo) and it's changed the way I work forever (in a good way, I think).
The thing that made me think of this was your first bullet: Zend framework does exactly this as it's standard way of accessing 'controllers' and 'actions'.
In terms of encapsulating and abstracting issues with different databases, Zend_Db this very well. Dojo does an excellent job of ironing out javascript inconsistencies between different browsers.
Overall, it's worth getting into good OOP techniques and using (and READING ABOUT!) frameworks has been a very hands-on way of getting to understand OOP issues.
For some standalone tools worth using, see also:
Smarty (template engine)
ADODB (database access abstraction)
Declare variables before using them!
Get to know the different types and the === operator, it's essential for some functions like strpos() and you'll start to use return false yourself.