PHP include_path getting \-escape processed "later" on Windows - php

I know how to fix this with brute-force prevention (I think), but I'm wondering if anyone has encountered this and/or come up with some good ideas for tracking down the real root cause.
I'm on Windows XP with php 5.4.31. I've set my include_path such that with xdebug I can see the result of get_include_path() to be:
C:/xampp1826/htdocs/OSH2/application/../library;C:\xampp1826\htdocs\OSH2\library;.;C:\xampp1826\php\PEAR
This is a ZF1 application that uses the Zend class autoloader, and that's what include_path() returns as various things get autoloaded successfully. Then "suddenly", just before attempting to autoload one particular class for which it has correctly computed the filename relative to the include_path, I can see that get_include_path() returns that string with each \xa sequence converted to a line feed (ascii decimal 10), causing the autoloader's include_once to fail.
I've done exhaustive searches for additional calls to set_include_path() (including all the php libraries I use), and there are only a couple. And I've put breakpoints on them and displayed the result of get_include_path() after each one. Doing that I haven't been able to find php code that actually makes the change! I suppose I could have missed a spot, and I'll re-check everything again after some sleep, but as things stand right now, it looks like a bug in php. In fact, once the right characters are in the include_path string, I can't even imagine how php code could easily/accidentally perform the escape processing. And although I can't easily switch back right now, I did not have this problem using php 5.3.1 on what I'm 99% certain was the exact same source code. Was there some kind of change in php 5.4 that might explain this?
Has anyone else seen something like this, and if so how did you track down the root cause?
Since php on windows is perfectly happy to accept forward slashes in pathnames rather than back slashes, my brute force prevention strategy is simply to ensure that no backslashes ever get into the include path, with code along the lines of:
define('APPLICATION_PATH', str_replace('\\', '/', realpath(str_replace('\\', '/', realpath(dirname(__FILE__) . '/../application')))));

I don't know the right procedure for this, whether the question should be deleted or marked some other way so that people don't spend more time on it...
But the particular problem as I described it appears to have been some sort of artifact in the combination of xdebug (php_xdebug-2.2.5-5.4-vc9.dll downloaded from http://xdebug.org/download.php) and Netbeans 7.4 that decided to convert the \xa character sequence to a linefeed character when displaying the string returned by get_include_path(). In fact, it only happened "sometimes", as repeated sessions in the debugger displayed it differently at the same point in the code.
I went ahead and changed the code to force the include path to use forward-slashes exclusively to eliminate that red-herring. But I still see the exact same problem, at the exact same point in the code, where a call to include_once() with a valid filename for a valid php file that does exist and is readable when appended to the first directory in the include_path simply kills my script without logging or reporting any error or warning. I'll post a different question with the details on that if it remains intractable now that I'm not chasing the red herring. I'm getting a bad feeling about php 5.4.31...

Related

Have script path with unresolved symlinks in PHP?

Let's say we have a web directory with the following paths:
framework/
index.php
...
instance/
index.php -> ../framework/index.php (symlink)
...
If we now make a request for (...)/instance/index.php PHP will resolve the symlinks and set __FILE__ as (...)/framework/index.php
Is there a way around this so e.g. dirname(__FILE__) would be (...)/instance?
EDIT: Since it has been pointed out, I'm actually not sure if PHP itself is resolving the links or something else. In my case I'm using nginx as a webserver with php-fpm as FastCGI.
(The background is that I want to have multiple instances of a CMS or Framework referencing a common code base.)
The best approximation for your case is dirname($_SERVER['SCRIPT_FILENAME']) to get the "instance" dir, if you can live with the general warning in the doc about the $_SERVER vars:
There is no guarantee that every web server will provide any of these;
servers may omit some, or provide others not listed here.
Also, the PHP manual does not explicitly promise that symlinks will be preserved, but that seems to be the case (unless of course your server thinks otherwise). See also this answer.
(Note: this also works in CLI mode. If the script was launched via a relative path (to the CWD), PHP will keep it that way, so you may end up with "." then.)
However, for the general problem (of getting any script's dir with symlinks preserved), this doesn't work. It only works for the script that has been reached via HTTP. Since any other scripts you include later on will all have the same $_SERVER['SCRIPT_FILENAME'] (of course), regardless of their location, dirname($_SERVER['SCRIPT_FILENAME']) will yield the wrong dir if they are located elsewhere...
I don't think PHP has a solution for that today (as of v7.2).
(And you were correct initially: PHP is doing the symlink-resolving for __FILE__, irrespective of your server. And it's unlikely that this would ever change, because it has stayed this way for too long (and too much code depends on it), even though there's realpath() if we wanted the resolved path, while there's no bullet-proof solution for the symlinked case.)

Including remote PHP file functions in local PHP file

Gone through related posts and found turning allow_url_include will does the trick. However when I did this :
remote file file.php at http://www.courierscripts.com
$content = file_get_contents('http://www.courierscripts.com/folder/file.php');
on my functions.php, was not able to use the functions of file.php. I also don't want to change my file.php to file.txt because everyone can see it.
Any other way?
If the file is on the same server, use absolute or relative path to it, not an url. Otherwise:
Short answer:
No, it's not possible.
Long answer:
Actually possible with conditions but I bet you won't like them.
It's obviously impossible if you don't have access to the target server (otherwise storing passwords in php config files like Wordpress does would be just one big security flaw).
First of all, file_get_contents returns a string. So you could eval it, but eval is very bad (you can search SO for the clues why).
OK, suppose you agree to eval what's coming from that server even after considering that someone might change the code and do whatever he wants on your machine. BUT you make an http request that is handles by the server (Apache, Nginx or whatever else).
The server knows that *.php files should not be handles as static files. For example, fastcgi. You can turn that off, for example, with RemoveHandler in Apache. But that would let everyone see the source code of files you expose this way.
So, after removing handlers and evaling the result, you could get the result. But be ready that someone you work with will punch you in the face for doing that ;)
UPD
For code sharing, use Composer to create a package and use it as a dependency.

wildcard not working to change directory

i cant use * or ? for change directory
chdir ("c:\win*\system*");
how it work, i cant guess full name of windows whats that, for example WIN or winxp or win7.
or how to guess whats full name of that
chdir() to a random wildcard directory supposed to be chosen by the system for you in case of collissions? Really?!
Paths are explicit. It's here or there... not somewhere, just look it up for me. And why try to access system directory from PHP in the first place? Got permissions setup right? Or you want to make modifications to users that use your script and can't guess the right path yourself?
Imagine that this guy's chdir() has to list paths in multiple
folders everytime to do one simple operation. Let's talk security,
performance... but most of all... common sense.
The things I see on SO...
PS: I -1'ed you. This question should not be asked by a developer with minimal understanding of... development stuff. Want to inject stuff into system dir, don't use PHP.
You are likely misunderstanding that chdir is equal to windows chdir (cd) in the windows operating system. But it is not.
However that should not pose you any problems because PHP and the shell can work together easily:
chdir(rtrim(`cd c:\win*\system* & cd`));
echo getcwd();
Example output:
C:\WINDOWS\system
If you know what command is for what, you can easily solve the issue.
Stumbled upon this:
CHDIR allows wildcards as path names, and changes to the first directory found whose name matches the wildcard specified. This is convenient with long directory names, as it is only necessary to type enough of the path to uniquely identify the directory, and then add a trailing "*" to the path name.
http://www.rcramer.com/tech/windows/cmd/ad.html#CHDIR
It is not PHP though...

get_browser() returns FALSE

- Running PHP 5.3.8 on Linux-
To start, we have solved this issue to the point where the function returns the expected values. However there are still a lot of unanswered questions I've got, and the "solution" is more of a hack-around than anything.
I've spent the better part of a day on this issue, so bear with me as I explain what was done. To start, the issue is that the return value of get_browser() is FALSE, which is not a documented return value. This leads me to assume that FALSE being returned means some sort of error state within the function.
The test code, after many iterations, became just a simple var_dump(get_browser($agent, true)). I ran tests with both passing the user agent string directly, as well as passing no arguments, e.g. var_dump(get_browser()), that all had the same return values.
What was tried/verified, with no change in return value:
browscap.ini:
Have the latest version, also tested a few previous versions
Permissions:
bowscap.ini - Initial permissions were 644, but I have tried everything from 644-777
Directory containing browscap.ini - Initial permissions were 755, tried 777 as well
Verified that PHP can access the file and directory with other functions like file()
User Agent
Tried passing a manual user agent string
Tried passing $_SERVER['HTTP_USER_AGENT']
Verified my user agent string with a friend in a far away land - get_browser() returned values as expected.
php.ini
The browscap setting points to the correct location
verified again with echo count(file(ini_get('browscap')));
Error Logs
Checked PHP & Apache error logs for any mention of 'browscap' or anything even closely related - nothing out of the ordinary.
File Structure
This is where I suspect that the error comes from. browscap.ini lives in /var/php/, which has suitable permissions as noted above. My thought was that maybe PHP couldn't access this directory, or something along those lines. However, this directory is also where sessions are stored, so that becomes less likely.
THE "SOLUTION"
What solved the issue was moving browscap.ini to the public web directory. I'm curious as to why this is the case, especially given the undocumented return value. The "solution" works, but is not the solution I thought I would find...
Does get_browser() have special permissions requirements, or anything like that? file() could access the directory and file just fine, but get_browser() could not (presumably). I've practically pulled my hair out over this issue and would love some resolution!
Thanks for reading!
You have tried around every required method.
http://php.net/manual/en/function.get-browser.php having note:
In order for this to work, your browscap configuration setting in php.ini must point to the correct location of the browscap.ini file on your system.
browscap.ini is not bundled with PHP, but you may find an up-to-date php_browscap.ini file here.
While browscap.ini contains information on many browsers, it relies on user updates to keep the database current. The format of the file is fairly self-explanatory.
What solved the issue was moving browscap.ini to the public web directory.
It is may be pointing to that location. i.e. public web directory
Does get_browser() have special permissions requirements, or anything like that?
Read permissions are required only.
Actually, even not documented on the manual page, the get_browser function can return FALSE for multiple reasons.
At least a look into the underlying source code let one assume that.
I suggest you take a look in there and then let me know if you have additional questions. I might be able to answer them then.
I had the exact same issue as the original poster. The solution? php.ini required an absolute path to the browscap.ini file.
So, even though PHP found the file and it appeared in phpinfo()'s output, the following line was the problem:
browscap = browscap.ini
With that line, getBrowser() returned false.
However, changing it to an absolute path worked, like so:
browscap = /etc/browscap.ini
Hope this helps someone! It's a strange one...

New line before header()

I'm working with a custom made Joomla script that generates an image from a blob in a database. However, when we moved it from an Apache server to an IIS server, the script is breaking.
Upon investigation, it seems that now, there is a line break that is getting appended before the header function is being run (when I comment out the image portion, and do an echo "test";, test gets printed on line 2 of the source code.
I've gone through the script over and over again, and through the many files in the component, and can't seem to find out where this new line is coming from. At all.
I've tried using ob_start() and many similar functions, but nothing seems to work.
I'm completely out of ideas, and don't know where to turn.
Is there a way to trace what files are being called in the page, perhaps? Any thoughts on further steps?
Look out for additional whitespace at the end of PHP files. If a PHP file ends in more than a single return after the last ?>, that stuff gets printed regardless of where the file is/was included. That is a common error source in larger PHP projects and would meet your symptoms.
(To circumvent this, some have started with a coding standard that prohibits the last ?> in their source files, which is perfectly legal PHP.)
Be careful, maybe it's an encoding problem. Open the file with vim under linux to see if there an ^M or something like that.

Categories