Althttpd

PHP how to?
Login

PHP how to?

(1) By Robert Hairgrove (bobhairgrove) on 2023-05-06 11:41:01 [link] [source]

I recently signed up for a little VPS running Linux Ubuntu 22.04 so that I could run Fossil with althttpd, and it seems to work quite well.

Now I am thinking about moving some other websites which are currently implemented almost exclusively in PHP on a LAMP stack over to my new VPS.

I know that any file content which is marked as executable will run the file as CGI. But I am wondering whether I need to add a shebang line at the top of all of my PHP scripts or not. Is there some way of telling althttpd that it should invoke PHP on a script WITHOUT the shebang?

The only idea I could come up with is to have a "shadow" directory tree with two-liner CGI scripts named the same as the original script for each PHP file and keep the original files out of the DOCUMENT_ROOT hierarchy where they could reside unchanged (they only need to be readable), something like this (/bin is in my chroot "/" folder and has a symlink to the real bash):

#!/bin/bash
php ../shadow/$SCRIPT_NAME

Assuming that $SCRIPT_NAME contains the name of this CGI script, I would probably have to mogrify the path it contains.

Are there any alternate ways of doing this?

(2) By Stephan Beal (stephan) on 2023-05-06 13:50:17 in reply to 1 [link] [source]

Is there some way of telling althttpd that it should invoke PHP on a script WITHOUT the shebang?

Nope. althttpd has no external configuration, so no way of telling it that. If it sees the file as executable then it simply passes it on to the OS to Do The Right Thing with.

(3) By jose i cabrera (jicman) on 2023-05-07 01:16:11 in reply to 2 [link] [source]

To add to Stephan's remark, I am using a python3 script for my index.html. This is the start of my index.html

jic@web:~/w/default.website$ head index.html
#!/usr/bin/python3
import sqlite3
import datetime
import string
import apsw
import os
import string
import sqlite3
import cgi, cgitb
import requests

It works.

(4) By anonymous on 2023-06-11 20:13:55 in reply to 3 [link] [source]

Wow. That's cool, but what sort of a delay are you getting before first paint on the client end?

(5) By jose i cabrera (jicman) on 2023-06-12 14:00:37 in reply to 4 [link] [source]

It depends on the network. But on a 300mbps network, I get instant < 1 sec response (haven't really timed it). From work is about 3secs, but that's because of the firewall. It does not have any graphics, so... It's running Ubuntu 22.04 (no X) on an old dual 2.5MGz CPU with an SSD MacBook. It does the job very well.

(6.1) By midijohnny on 2024-05-09 21:25:13 edited from 6.0 in reply to 1 [link] [source]

Here's a starter - far from perfect - but I'm not a PHP expert, so others may be able to help flesh this out.

Issues:

  • The 'header' function in PHP - doesn't output in 'interactive' mode - hence using 'echo' directly within the output stream to create the necessary "Content-type" header.
  • The automatic variables don't get initialised - so nothing in $_REQUEST.

I guess we could feed in the shell's automatic variables '$QUERY_STRING" etc into the PHP script somehow.

I wonder if there is an option for PHP scripts to do these automatically though. (the ENV[xx] function doesn't seem to see the environment either in 'interactive' mode).

#!/usr/bin/php
# Save this as 'myscript.php'
# Ensure appropriate permissions set (eg. chmod 700 myscript.php).
<?php echo "Content-type: text/html" .  PHP_EOL .  PHP_EOL?>
<html>
<head/>
<body>
<?php
    echo "hello";
?>
</body>
</html>
curl --verbose http://localhost:8080/myscript.php
*   Trying 127.0.0.1:8080...
* Connected to localhost (127.0.0.1) port 8080 (#0)
> GET /myscript.php HTTP/1.1
> Host: localhost:8080
> User-Agent: curl/7.81.0
> Accept: */*
> 
* Mark bundle as not supporting multiuse
< HTTP/1.1 200 OK
< Connection: keep-alive
< Date: Thu, 09 May 2024 21:02:11 GMT
< Content-type: text/html
< Content-length: 43
< 
<html>
<head/>
<body>
hello</body>
</html>
* Connection #0 to host localhost left intact

(7) By Stephan Beal (stephan) on 2024-05-09 21:33:35 in reply to 6.1 [link] [source]

chmod 700

A tip, if i may: chmod 0500 is safer, as it prohibits overwriting of the file unless a script first makes it writable. Back when i used WordPress, using chmod -w on all files it installed eliminated a problem where a buggy theme permitted crackers to overwrite files and hijack the site.

(8) By midijohnny on 2024-05-15 10:05:11 in reply to 6.1 [source]

The following works: but be very cautious about using it. If you use 'php-cgi' instead of 'php' like this:

#!/usr/bin/php-cgi
<?php
# filename: hello.php
echo 'hello world';
?>

Ensure the permissions are set to a suitable value:

$ chmod 0500 hello.php
$ althttpd

You will see a warning message when you navigate to the page (hence the note about being cautious above):

This PHP CGI binary was compiled with force-cgi-redirect enabled. This means that a page will only be served up if the REDIRECT_STATUS CGI variable is set, e.g. via an Apache Action directive.

For more information as to why this behaviour exists, see the manual page for CGI security.

For more information about changing this behaviour or re-enabling this webserver, consult the installation file that came with this distribution, or visit the manual page.

If you now stop 'althttpd' and set the environment variable referenced above, and re-run althttpd:

$ export REDIRECT_STATUS=whatever_value_you_want
$ althttpd

The program will run. I tried a slightly more complicated script - which also worked:

#!/usr/bin/php-cgi
<?php
# filename: form.php
header('Content-Type:text/html');

switch($_SERVER['REQUEST_METHOD']) {
    case 'GET':
        ?>
            <form action="form.php" method="post">
                <label for="fname">First name:</label><br>
                <input type="text" id="fname" name="fname" value="John"><br>
                <label for="lname">Last name:</label><br>
                <input type="text" id="lname" name="lname" value="Doe"><br><br>
                <input type="submit" value="SUBMIT">
            </form>
        <?php
        break;
    case 'POST':
        ?>
            <table>
                <thead>
                    <tr>
                        <th>fname</th> <th>lname</th>
                    </tr>
                </thead>
                <tbody>
                    <tr>
                        <td><?=htmlspecialchars($_POST['fname'])?></td> <td><?=htmlspecialchars($_POST['lname'])?></td>
                    </tr>
                </tbody>
            </table>
            <a href="javascript:window.location.href=window.location.href">back to form</a>
        <?php
};
?>

NOTE: I don't know why: but I had to include the header function to set the content-type here to get this to work (I didn't need to for the simple example). Without this - the PHP SOURCE is returned to the client. Therefore: be careful with this approach.