• This forum has a zero tolerance policy regarding spam. If you register here to publish advertising, your user account will be deleted without further questions.

[HowTo] PHP4/PHP5 as CGI - patched (English HowTo)



Hey guys,

there you go, this is the long expected, ultimate, most awesome (etc) HowTo ;)

Hinweis: Bitte klicken Sie hier um die deutsche Version zu sehen.

Purpose of this HowTo is:
- To have PHP4 and PHP5 run in parallel
- To not abandon PHP's open_basedir, even though running it with CGI or using Apache's mass-hosting module (mod_vhost_alias)

- Linux-Webserver
- Apache 1.xx or 2.xx
- good knowlegde of linux (basic linux skills are required!)
- 20 minutes of your (spare) time
- 20 litres of beer (optional)

Let's start with a lil story of how it came to this HowTo:
Every experienced serveradministrator is familiar with the following problem: you are running PHP4 (in most cases as Apache module) and at the same time you wanna use PHP5. Since it is not possible having 2 PHP versions running as Apache modules you need to think of some sort of a patch (or whatever you want to name it). You already might have asked Google...
Basically there are 3 solutions offered by Google search:
1. Run the 2.nd PHP version as CGI
2. Install a 2.nd instance of Apache (complicated and in most cases not very useful [dumb solution])
3. only run one version at a time (doesn't solve our problem at all [screw this solution])
So let's take a look at #1:
First you might think "yes awesome, that's the most wicked solution". After a couple of hours you then realize that it actually isn't as perfect as you first thought. (Hint: reading the next few lines could save you some time)
The problems connected to the CGI edition of PHP:
1) open_basedir (very important security feature of PHP) is not available through Apache config files anymore.
2) right now I cant think of any other problems (except for the reduction of speed, which is not solvable)
First issue can be solved the following ways:
a) using suPHP or fastCGI
b) this HowTo (way better, since it works very well with a large amount of vhosts or mod_vhost_alias)
I only offer a HowTo for b) at the moment. If you are still interested: keep on reading ;)
We are now going to edit the source of PHP! (it's pretty easy... ;))
This workaround should work just fine. I have tested it several times on different servers and systems.
You don't need to be a C-Programmer for editing the source ;)
So, I better shut up now and start the step by step HowTo:

1. Get the PHP sources:
 wget http://de3.php.net/get/php-5.0.5.tar.gz/from/this/mirror
2. unzip/untar:
 tar xfz php-5.0.5.tar.gz
3. cd into dir:
 cd php-5.0.5
3. execute configure
 ./configure --prefix=/usr/share/php5 --datadir=/usr/share/php5 --bindir=/usr/bin/php5 --libdir=/usr/share/php5 --with-config-file-path=/etc/php5 --with-exec-dir=/usr/lib/php5/bin --enable-memory-limit [B]--enable-force-cgi-redirect[/B] --enable-track-vars [B]--with-mysql=/usr[/B] --without-pear --enable-session --without-sqlite --enable-exif
--enable-force-cgi-redirect is needed by CGI version. Don't use apxs/apxs2!
--with-mysql=/usr MySQL needs to be included in PHP5 (if you dont want to have MySQL support.. just leave it out;))
5. hit ENTER!
6. Wait (be patient). Configure is being executed. This may take some time. Any errors? >> Ask Google! Most of the time configure complains about missing header files. In order to solve this problem you need to install them (devel-packages).
7. (optional) The first 0,5l of beer can be drunk. Depending on your server (speed) you can think about drinking another 0,5l afterwards ;)
8. Configure has now successfully finished configuring your PHP source. Congratulations ;)
9. Now comes the good part! We are going to patch PHP now:
a) Open the file /php-5.0.5/main/fopen_wrappers.c with your favorite editor (e.g. with vi)​
b) Search for line
[COLOR=Indigo][COLOR=Black]PHPAPI int php_check_open_basedir_ex(const char *path, int warn TSRMLS_DC)[/COLOR][/COLOR]
This is the function we are about to modify!​
c) Let's point our cursor to the following section:
[COLOR=Indigo][COLOR=Black]if (PG(open_basedir) && *PG(open_basedir)) {[/INDENT][/INDENT]
[INDENT][INDENT]                char *pathbuf;[/INDENT][/INDENT]
[INDENT][INDENT]                char *ptr;[/INDENT][/INDENT]
[INDENT][INDENT]                char *end;[/COLOR][/COLOR]
d) Now comes the tricky part... we insert the following code:
   /*faked base_dir */[/INDENT][/INDENT]
[INDENT][INDENT]                char awesome[MAXPATHLEN];[/INDENT][/INDENT]
[INDENT][INDENT]                char pathstuff[MAXPATHLEN];[/INDENT][/INDENT]
[INDENT][INDENT]                int counter = 0;[/INDENT][/INDENT]
[INDENT][INDENT]                strlcpy(awesome, "", sizeof(awesome));[/INDENT][/INDENT]
[INDENT][INDENT]                strlcpy(pathstuff, SG(request_info).path_translated, sizeof(pathstuff));[/INDENT][/INDENT]
[INDENT][INDENT]                int i;[/INDENT][/INDENT]
[INDENT][INDENT]                for(i = 0; pathstuff[i]; i++)[/INDENT][/INDENT]
[INDENT][INDENT]                    {[/INDENT][/INDENT]
[INDENT][INDENT]                    if(pathstuff[i] == '/')[/INDENT][/INDENT]
[INDENT][INDENT]                    counter++;[/INDENT][/INDENT]
[INDENT][INDENT]                    if(counter == [COLOR=Red][B]6[/B][/COLOR])[/INDENT][/INDENT]
[INDENT][INDENT]                        {[/INDENT][/INDENT]
[INDENT][INDENT]                        pathstuff[i+1] = 0;[/INDENT][/INDENT]
[INDENT][INDENT]                        strlcpy(awesome, pathstuff, sizeof(awesome));[/INDENT][/INDENT]
[INDENT][INDENT]                        break;[/INDENT][/INDENT]
[INDENT][INDENT]                        }[/INDENT][/INDENT]
[INDENT][INDENT]                    }[/INDENT][/INDENT]
[INDENT][INDENT]                strlcat(awesome, ":/other/base/dirs/dude/:/tmp/", sizeof(awesome));[/INDENT][/INDENT]
[INDENT][INDENT]                /* end! */
Explanation of the code (please read carefully!):
The patch is based on the following thinking:
Every webhoster should have a certain structure (directory tree).
Doc_Root: /home/www/hostedstuff/users/username/
Please note that /username is replaced by a username or something.
Our faked basedir checks the scriptpath of every php file which is executed and determines the Doc_Root this way.
The scriptpath is searched for "/". In this case (example) the loop runs through it 6x and saves the result into a string (our Doc_Root).
Username: sweetheart​
This user now runs the script fools.php in dir /donuts.​
Script-Path: /home/www/hostedstuff/users/sweetheart/donuts/fools.php
The scriptpath is now going to be analyzed by our patch. The patch will lock the user into the following doc_root:​
Optionally you can add several static open_basedirs (seperated by ":"), otherwise comment it out.​
d) Now we need to modify the call of the following function:​
   pathbuf = estrdup(PG(open_basedir));
is replaced by:​
   pathbuf = estrdup(awesome);
e) save the file (no explanation needed I guess ;))​
f) exit the editor.​
g) successfully patched! Congratulations. It took you only 5minutes to patch the open_basedir... but never forget: this would never have been possible without having a person like me who spent about 5months finding/creating such a solution. Please keep this in mind and don't laugh at my bad C-Programming.​
h) (optional) drink another beer ;)
10. make:
11. Waiting... (open another beer and chuck it)
12. No errors? Awesome!
 make install
13. Wait. Files are being installed.
14. PHP installation is done
15. Now we need to include the CGI stuff into Apache
16. Insert the following into a vhost file or httpd.conf or something:
 <Directory "/usr/bin/php5">
AllowOverride None
Options +ExecCGI +FollowSymLinks
Order allow,deny
Allow from all
ScriptAlias /php5rocks /usr/bin/php5
Action php5-cgi /php5rocks/php
AddType php5-cgi .php5
17. It is recommended to use suexec!
But this is off topic and I don't offer a HowTo on how to configure suexec (haha, what a wordplay!).
Nevertheless: this link could be helpful:
18. Every *.php5 file is now parsed by our PHP5 CGI version!
19. Finally done!
20. You made it!
21. Chuck the rest of your beers!

This HowTo is also usable for PHP4!
As I already mentioned: I spent MONTHS building this patch... if you found it helpful, feel free to donate some money to CwCity.de (paypal).
Please note: I do not offer any free support neither on MSN nor on ICQ!
If you have questions/comments/anything else: feel free to reply to this Thread!

This HowTo comes with NO WARRANTY!

Copyright © 2005 by server4downs & CwCity.de

Last Update: 14th of November 2005 (9:45pm)
Last edited by a moderator: