LAMP

Often the term LAMP appears, LAMP stands for Linux, Apache web server, MySQL database, PHP programming language. For Linux read this book, for apache go to the apache section.

PHP

PHP is the Hypertext Preprocessor that is installed on the web server. PHP is used to create a dynamic HTML page. Those pages are the result when pages as index.php are called. In the other direction PHP can interpret data being arrived from a user (client, web browser). This happens when forms are sent back to the web server.

When a browser request a page, then the web server sends a header (where the MIME type is defined) following the HTML page.

If the requested page is a page as index.php, then the server loads this page in memory, but instead of sending it out, it is passed to a PHP interpreter. Try out the following index.php

<?php
echo "Hello World";
?>

The PHP interpreter creates what ever is echoed and sends it out.

To not have to create the complete web age, PHP is embedded in HTML containing something as:

<html>
<body>
<?php
echo "Hello World";
?>
</body>
</html> 

However the above probably won't execute the php. The reason is that apache interprets the file as html, won't parse it and sends it out as it is.

For apache load the php module in /etc/conf.d/apache2

APACHE2_OPTS=" <other -D stuff > -D PHP5"

To install php emerge php and have apache note about it by /etc/init.d/apache2 restart. Create a simple HTML page with the name index.php and put it under /var/www/localhost/htdocs/index.php :

<html>
  <body>
    <?php 
      phpinfo(); 
    ?>
  </body>
</html>

Then type in your browser http://127.0.0.1/index.php and you should see a full featured php info page. To see what and if apache2 supports php eselect php list apache2

CGI

With CGI (Common Gateway Interface) your web browser (HTTP client) can initiate a communication with the HTTP server and as result some code is running on the server. This sounds easy, however this time you send the data to the HTTP server, the server takes it, does something with it and responds back to your HTTP client the browser.

To keep it simple a basic sample explaining the concept is more helpful than writing pages showing how the data sent to the server, how it is structured, what buttons and forms HTML supports, how the server interprets the data and last but not least showing you a blown Perl script (if you are Perl newbie than you are probably lost when reaching this point),

Here the example script put on the server:

#!/bin/sh
echo Content-type:text/plain
echo 
/bin/date

The script is easily explained, #!/bin/sh tells the server that it has to start it as a regular script. The first echo tells to the server, that it will receive plain text from the CGI executable and finally /bin/date prints date and time in plain text. The server then takes this plain text and send it back to your browser nude as it is. Hopefully your browser understands naked plain ASCII and will show something as:

Sun Aug 17 13:47:11 EDT 2008

An easy test is just typing the following URL into your web browser:

http://127.0.0.1/cgi-bin/getdate.cgi or http://www.linurs.org/cgi-bin/getdate.cgi or http://www.linurs.org/cgi-bin/getdate.cgi

This is also a good test if everything works, since many servers have lots of restrictions.

Important

If a symbolic link is used to point to the cgi script, then the web server might to refuse to start the script due to security issue.

The following line can be put in a html page:

      <a href="http://www.linurs.org/cgi-bin/getdate.cgi">Show the  date</a>

It is nothing else than a Hyperlink, but this time not to a HTML page but to a cgi executable. This gci executable can be everything that runs on the server: A binary, a Perl, python or bash script. If you have the necessary permissions than the server starts this executable after you have clicked on the Hyperlink.

The CGI executable could look as the following bash script:

The server does just a little bit more than just executing the script, it has deviated the stdout, so everything the script prints ends up on the HTTP server application itself. This explains that CGI can make use of all programming languages that can print. Script languages need an interpreter to run, as the bash script needs bash available on the server, for Linux no problem, but for a Windows server a problem.

The above sample could send back other MIME types as text/html, image/gif, image/jpeg, video/mpeg. Sending back HTML, the sample could look as follows:

#!/bin/sh
echo Content-type: text/html
echo
cat <<_End_
  <HTML>
  <HEAD>
  <TITLE> Date </TITLE>
  </HEAD>
  <BODY>
  <P> The Date is:<B>
_End_
/bin/date
cat <<_End_
  </B> <P>
  </BODY>
  </HTML>
_End_

Instead of creating some data, that will be send back, you could also pass back a link:

echo Location: /index.html

replaces the echo Content-type line.

A more complex CGI example would show how a form is created on a web page, how all the data inside the form is sent to the http server, how the server gets the data and passes it to the CGI executable, how the CGI executable interprets the data and maybe creates files on the server or interacts with a data base, and finally how it returns more than just nude plain ASCII, since usually the GCI executable returns a HTML page back to the http client (your browser).

Finally you can call a GCI script through the net:

http://www.linurs.org/cgi-bin/getdate.cgi

It is also possible to install a terminal application and use it via cgi. The package cgiterm https://sourceforge.net/projects/cgiterm/can be put under the cgi-bin directory and be started: http://www.linurs.net/cgi-bin/cgiterm/cgiterm.pl

Passing data to the CGI script is done by attaching ?<var1name>=<value1>&<var2name>=<value2> to the url. Languages as python have a parser to extract the data from the string

#!/usr/bin/python3
import cgi
para=cgi.FieldStorage()
print("Content-Type: text/plain")
print()
print(para.getvalue("<name of the value>"))

Usually the GET request (an alternative would be using POST) of the HTTP protocol is used to pass the string and therefore the data ends up in the QUERY_STRING variable. Python and most other programming languages allow also to read environmental variables:

#!/usr/bin/python3
import os
print("Content-Type: text/plain")
print()
print(os.getenv('QUERY_STRING'))

So when developing CGI scripts

declare -x QUERY_STRING="<var1name>=<var1>&<var2name>=<var2>"

sets the environmental variable

Finally the cgi script has environmental variables where it can find out things about the one looking at the page http://www.linurs.org/cgi-bin/getenv2.py tells you who you are including your IP and services as https://ip-lookup.net/ then tell you where you are.

The above python 2 script could look as simple as

#!/usr/bin/python
import cgi
print "Content-Type: text/html"
print
cgi.print_environ()
cgi.print_directory()
cgi.print_environ_usage()

Or more easy use things as ip2country from http://freenet.mcnabhosting.com/python/ip2country/

FCGI and SCGI

Regular CGI are scripts that are getting called and terminated when a web browser calls them. In case of having a python script, this means first the python interpreter must be loaded and then the script can be started and finally everything is unloaded. This can mean a huge overhead for just a couple of script lines.

FastCGI (or FCGI) or FCGI is Simple Common Gateway Interface (SCGI) solves this by loading the CGI script once and uses it for many requests. The script communicates with the web server via a TCP/IP socket (and could therefor be even on an other machine). Both are standardized so SCGI and FCGI can be used on different web server implementations. As a result FGCI and SGCI scripts are no more simple scripts since they need to implement the TCP/IP protocols (they are now similar as daemons running in background and serving requests).

The procedure is that the server has to be setup to start these scripts. The server has to find out what files it can simple send to the browser and what files are really requests for FCGI and are really not files. The above scripts have to interpret such requests and send back to the server.

The socket protocol required to have the fastcgi server taking to lighttpd can be handled by different implementations.

A quite commonly used but badly documented, old and no more maintained implementation is flup and flup is just available for python2 (version 1.0.2). It has sphinx documentation. So change to docs subdirectory and make html

However some people ported flup to python3 but unfortunately this is not very coordinated, (there might be many different 1.0.3 versions around). I found one that after patching worked. I informed the developers about the patch and then the whole thing disappeared from the Internet. Luckily Gentoo kept the source on my PC, so I simply forked it and now also I'm one of the many having his own python3 flup version.

It should be noted that the script below will work for many web server as lighttpd or apache, since it follows the fastgci standard.

A fastcgi script doing this could look like:

#!/usr/bin/env python2
# -*- coding: UTF-8 -*-

import sys, os
from cgi import escape
from flup.server.fcgi import WSGIServer

def app(environ, start_response):
  start_response('200 OK', [('Content-Type', 'text/html')])
  yield '<h1>FastCGI Environment</h1>'
  yield '<table>'
  for k, v in sorted(environ.items()):
    yield '<tr><th>{0}</th><td>{1}</td></tr>'.format(
      escape(k), escape(v))
  yield '</table>'

WSGIServer(app).run()

A flup.https://pypi.python.org/pypi/flup simple hello world python FCGI script flup would look:

#!/usr/bin/python2.5
def myapp(environ, start_response):
    start_response('200 OK', [('Content-Type', 'text/plain')])
    return ['Hello World!\n']

if __name__ == '__main__':
    from flup.server.fcgi import WSGIServer
    WSGIServer(myapp).run()

Environ is a python dictionary that contains all the stuff as the QUERY_STRING that could be extracted via query=environ["QUERY_STRING"]

There is also webpy that allows selecting different objects to be started using its urls variable that contains a regular expression and the matching object to be started.

#!/usr/bin/python import web

urls = (
    '/(.*)', 'test'
)

handler = web.application(urls, globals(), True)

class test:
    def GET(self, name):
        return "It works!"

if __name__ == "__main__":
    handler.run() 

Wsgi

WSGI is the Python Web Server Gateway Interface that serves as middle-ware between a web server and python.

A server that can handle wsgi is uwsgi http://uwsgi-docs.readthedocs.io/en/latest/ unfortunately it is a monster where it is difficult to get an overview.

SSI

Scripts could also be started when the web page is loaded.

Note

This is not CGI where the client initiates that code is running by sending data to the server. It is the server that has to know that it has to run code when a page is requested.

Note

With SSI take care that you do not could cause an recursive loop.

To enable SSI (and call a CGI script), just add a special comment:

      <!--#include virtual="/cgi-bin/<name of the script>.cgi"-->

Note

To work the server needs to be configured, to interpret such lines.

Ajax

AJAX (Asynchronous JavaScript and XML) Allows to exchange data with the web server and modify the web page without re-loading it. The web page contains javascript and sends out a XMLHttpRequest (using GET or POST since it must use the HTTP protocol) to the server and then receives the response behind the scene. Then Javascript is used to modify the web page accordingly. Ajax is a method of combining things to do it and is not something to be installed. However just browsers of the current century support XMLHttpRequest and therefore Ajax.

What is received can be either text or xml and it can be a file or output from a script. If it is xml then DOM is used to extract the desired information from xml.

The following example reads text output from a cgi script:

<html>
<head>
<title>Temperature</title>
<script type="text/javascript">
function RunMe()
{
  var xmlhttp;
  xmlhttp=new XMLHttpRequest();
  xmlhttp.open("GET","../cgi-bin/temperature.cgi",false);
  xmlhttp.send();
document.getElementById("myDiv").innerHTML=xmlhttp.responseText;
  t=setTimeout('RunMe()',1000);
}
</script>
</head>
<body>
<body onload="RunMe()">
<p>Ajax way to update the text below</p>
The temperature is
<div id="myDiv"><h2>AJAX</h2></div>
</body>
</html> 

The text identified by the id="myDiv" is periodically updated using javascript. xmlhttp.open uses false this means ajax does not run asynchronous but synchronous (Synchronous JavaScript and XML). This means the open command stops until the response has been arrived. This might be ok. But if there are many things to do, waiting is no more an option, so asynchronous is desired. This is done by using a callback function. The request is sent out and then immediately other things can be done. If the response comes back some time later, then the call back function is executed to process the response. Since javascript is an interpreted language, the call back function has to be declared before the open and send methods are called:

<html>
<head>
<title>Temperature</title>
<script type="text/javascript">
function RunMe()
{
  var xmlhttp;
  xmlhttp=new XMLHttpRequest();
  xmlhttp.onreadystatechange=function(){
    if (xmlhttp.readyState==4 && xmlhttp.status==200){
document.getElementById("myDiv").innerHTML=xmlhttp.responseText;
    }
  }
  xmlhttp.open("GET","../cgi-bin/temperature.cgi",true);
  xmlhttp.send();
  t=setTimeout('RunMe()',1000);
}
</script>
</head>
<body>
<body onload="RunMe()">
<p>Ajax way to update the text below</p>
The temperature is
<div id="myDiv"><h2>AJAX</h2></div>
</body>
</html> 

Access counters

It seems very simple to have an access counter to count how many times the web page has been accessed. If you are lucky your host provider offers you a solution. If not, then it can get complicated!

An easy way is a shtml using SSI or a php page, that is dynamically built when it is accessed, so just some code to read the actual value from a file, display it, increment it and store the result back to the file is required. But a pain is the dynamically creation of the web pages (and maintenance them afterwards).

Figure 8.2. Access counter

accesscounter


But you probably would like to keep your html extension of your web pages and just add some small thing to it. If you are lucky you can give your files the x permission and use SSI.

If none of those options worked, you can put a static string as the following in your HTML page:

      <IMG SRC="cgi-bin/graphical-counter">

It represents a graphical file created by a GCI script. The GCI script has to deliver a MIME type and the graphical file attached.

It is quite a hack, but since the HTML servers are made for static HTML pages, this is a quite common approach. The graphical file has to be obviously created using the counter value.

The binary

Now some instructions (GIF files containing single numbers are attached together to form the counter value):

I originally used the c code found on the Internet, but I modified it to have individual pages supported.

The size constants of the downloaded GIF files needs to match with the settings in the code (int real_height = 13 and int real_width = 9)

After emerge gd it can be compiled gcc -o graphical-counter -lgd graphical-counter.c

Since the access counter supports multiple pages, the page number needs to be defined, this is done with the exported environmental variable:

declare -x QUERY_STRING=page=count

The access counter program can therefore read the exported environmental variable and knows what page counter to be counted.

If you run ./graphical_counter you get some weird response:

Content-type: image/gif GIF87a<????,<v????S?ko?Lo?I??"p.g?ql???Ҫ??????kPI? ?H_??=?q???:I?.64???1(?\&?I9?N??n??,֯x?5?75???6????U?uX?89Y;

This is actually a ASCII header and the binary gif file all in one string.

For further debugging, you would like to split it. So run the program as ./graphical_counter > test.gif then open test.gif with an hex editor (as GHex) that understands pure binary and delete the first bytes until G is the word GIF is the fist character. Then save it and you have your image that you can observe in a picture viewer.

Installing on the server

To having running on the server there might be different obstacles especially when the server is not the same computer where you developed the access-counter.

The server probably does not know what versions of the libraries you have used at compilation time and therefore fail. To avoid that recompile the code.

The access counter makes use of the gd library, that is dynamically linked. If the access counter gets copied from the local Gentoo PC having the gd library installed to some Internet server without having the gd library installed, then the access counter fails. If so, you need to statically link the gd library into the access counter (and also the math library).

gcc -o graphical-counter graphical-counter.c /usr/lib/libgd.a /usr/lib/libm.a

or add -static to get rid of the dependencies.

An other way is not using C, and write/use an counter that is written in a language as python that is interpreted on the machine where the server resides. It will run slower but with less hassle.

Move the working directory to your server where it accepts cgi-bin. A first test to see if your script is found and even runs type the following url into your web browser.

You should now see a nice gif number that increments each time you click on the reload button of you browser. If it does not increment then you do not have write access to the file.

Now add a HTML page to your server that calls it

Example 8.1. Access Counter

<HTML>
 <HEAD>
   <TITLE>Example of the Graphical Access Counter</TITLE>
 </HEAD>
 <BODY>
  <H1>Graphical Access Counter</H1>
  This is my Home page. Thank you for visiting. Please come    again.
  <P>This page has been accessed 
<IMG SRC="/cgi-bin/accesscounter/graphical-counter?page=index">
</IMG> times.
 </BODY>
</HTML>


Linurs Servernest startpage