PHP/FI Version 2.0

Table of Contents

  1. Brief History
  2. Installation Instructions
  3. So, what can I do with PHP/FI?
  4. CGI Redirection
  5. Security Issues
  6. Safe Mode
  7. Running PHP/FI from the Command Line
  8. HTTP Authentication
  9. Apache Request Variables
  10. Apache Module Notes
  11. Apache Module Configuration Directives
  12. FastCGI Support
  13. Access Control
  14. Access Logging
  15. Relative vs. Absolute URL's - or, Why do my Images Break?
  16. How PHP/FI handles GET and POST method data
  17. GD (a graphics library for GIF creation) Support in PHP
  18. PHP/FI and Virtual Hosts
  19. File Upload Support
  20. Cookie Support
  21. mSQL Support
  22. Postgres95/PostgreSQL Support
  23. mysql Support
  24. Solid Support
  25. Sybase Support
  26. Oracle Support
  27. Regular Expressions
  28. Escape Characters
  29. Octal notation of Unix file permissions
  30. PHP/FI Script Language
  31. Adding your own functions to PHP/FI
  32. Notes for Code Hacks

Brief History

PHP began life as a simple little cgi wrapper written in Perl. I wrote it in an afternoon during a period between contracts when I needed a quick tool to get an idea of who was reading my online resume. It was never intended to go beyond my own private use. The web server where I had my resume was extremely overloaded and had constant problems forking processes. I rewrote the Perl wrapper in C to get rid of the considerable overhead of having to fork Perl each time my resume was accessed.

Eventually other people on the same web server came across my wrapper and asked if they could use it. Then, as inevitably happens, they started asking for more features. I added more features and finally put together a semi-complete distribution along with documentation, a mailing-list and a FAQ. The name of this first package was Personal Home Page Tools, which later became Personal Home Page Construction Kit.

At the same time I started playing with databases and wrote a tool to easily embed SQL queries into web pages. It was basically another CGI wrapper that parsed SQL queries and made it easy to create forms and tables based on these queries. This tool was named FI (Form Interpreter).

PHP/FI version 2.0 is a complete rewrite of these two packages combined into a single program. It has now evolved to the point where it is a simple programming language embedded inside HTML files. The original acronym, PHP, has stuck. It isn't really appropriate any longer. PHP/FI is used more for entire web sites today than for small Personal Home Page setups. By whatever name, it eliminates the need for numerous small Perl cgi programs by allowing you to place simple scripts directly in your HTML files. This speeds up the overall performance of your web pages since the overhead of forking Perl several times has been eliminated. It also makes it easier to manage large web sites by placing all components of a web page in a single html file. By including support for various databases, it also makes it trivial to develop database enabled web pages. Many people find the embedded nature much easier to deal with than trying to create separate HTML and CGI files.

Throughout this documentation any references to PHP, FI or PHP/FI all refer to the same thing. The difference between PHP and FI is only a conceptual one. Both are built from the same source distribution. When I build the package without any access logging or access restriction support, I call my binary FI. When I build with these options, I call it PHP.


Installation Instructions

Before You Begin

If you have absolutely no Unix experience, you may want to ask around for someone with a little bit of Unix knowledge to help you through this installation. Every attempt has been made to make it as simple as possible, but since the software is quite involved and relies on a number of different components, it is not realistic to assume it will go smoothly on all systems. You will probably need someone around who knows the particulars of the destination system well.

Things You Need To Know Before Installing

- Can you run both get and post method cgi programs on your server?
This is not relevant if you installing the Apache module version. If not, you can not use this package. On many public ISP's CGI programs are either disallowed or severely restricted. If this is the case on your system, talk to your system administrator and ask him/her to have a look at this package and see if they will install it for you.

- If you have mSQL installed on your system, you need to know the base directory of this installation.

- If you have Postgres95 or PostgreSQL installed on your system, you need to know the base directory of this installation.

- If you are going to be storing log and access configuration files in an NFS-mounted directory and your system does not provide NFS file locking then you will need to define the NFS_HACK variable manually in the src/Makefile and you may want to use a slightly modified version of the gdbm library. See the nfs_hack.txt file in the doc directory for more information on this.

- Note that if you are not interested in using PHP to track accesses to your pages, do not compile this option into the binary. You should also leave out the access restriction code. There is considerable overhead in including these options.

- If you are installing the Apache module version, you will need to know the Apache src code directory location.

Installation Steps

Step 1.

Run the install program: ./install

You will be asked a number of questions. If you do not understand what is being asked, simply hit return. The default choice should be safe on most systems. This doesn't apply for the questions asking you to specify a directory for your configuration and log files however. Choose any directory to which the httpd (usually "nobody") has write privileges. You may create this directory manually somewhere and simply chown nobody directory.

Step 2.

Go into the src directory: cd src

Have a look at the php.h file. There are a number of compile-time options that can be set here.

Step 3.

type: make

This will create the actual executable program file named php.cgi by default, or if you are installing the Apache module, it will create a libphp.a file.

Step 4. (if you are not installing the Apache module version)

Copy the php.cgi binary to your system's cgi-bin directory. If you do not have access to do this and wish to install it in your own personal directory, you may do so, but you should set the setuid bit on the executable with: chmod u+s /path/php.cgi

If you do not make set the setuid bit on the binary then any files created by the binary will be owned by the user id under which the web server runs. If this is acceptable, then you can safely leave the setuid bit off.

Step 4. (if you are installing the Apache module version)
Change to your Apache src directory where the mod_php.c and mod_php.h files should have been copied to. If they weren't which usually happens because of permission problems, copy these two files there manually. Edit your Apache Configuration file and add the EXTRA_LIBS line which was produced at the end of Step 3. And add:

Module php_module mod_php.o

to the very end of the file. Then type: ./Configure and then make to rebuild your Apache httpd binary. Install this binary.

Next you need to edit your Apache conf/srm.conf file and add a line like:

AddType application/x-httpd-php .phtml

This defines a new MIME, application/x-httpd-php, which will trigger the PHP module to parse any file ending with the .phtml extension. You can pick any extension you like for this.

You may not want to enable everyone to run PHP parsed files. You can place the above AddType line within <Location /path>....</Location> directives in the access.conf file to only allow PHP-parsed documents in certain directories on your server.

Now you are ready to restart your httpd server. See the Apache Module Notes for more details on configuring the PHP Module.

Testing the software

Once installed you can test to see if your executable works by entering a URL similar to the following in your browser:

http://your.site.domain/cgi-bin/php.cgi

This should show you a page which contains the version number along with various other useful information.

To test the Apache module version, create any file with a .phtml extension and put a tag like: <?phpinfo()> in the file and see if it gets parsed.

Using the software

To actually use the software on an existing HTML file, you can simply append the path to your file to the above URL. ie.

http://your.site.domain/cgi-bin/php.cgi/path/file.html

You should have a look at the CGI Redirection section of this documentation. Running PHP/FI through a redirect means you can automatically have a URL like http://your.site.domain/file.phtml be parsed by PHP/FI.

This does not apply to Apace module users.


So, what can I do with PHP/FI?

The first thing you will notice if you run a page through PHP/FI is that it adds a footer with information about the number of times your page has been accessed (if you have compiled access logging into the binary). This is just a very small part of what PHP/FI can do for you. It serves another very important role as a form interpreter cgi, hence the FI part of the name. For example, if you create a form on one of your web pages, you need something to process the information on that form. Even if you just want to pass the information to another web page, you will have to have a cgi program do this for you. PHP/FI makes it extremely easy to take form data and do things with it.

A simple example

Suppose you have a form:

<FORM ACTION="/cgi-bin/php.cgi/~userid/display.html" METHOD=POST>
<INPUT TYPE="text" name="name">
<INPUT TYPE="text" name="age">
<INPUT TYPE="submit">
</FORM>

Your display.html file could then contain something like:

<?echo "Hi $name, you are $age years old!<p>">

It's that simple! PHP/FI automatically creates a variable for each form input field in your form. You can then use these variables in the ACTION URL file.

The next step once you have figured out how to use variables is to start playing with some logical flow tags in your pages. For example, if you wanted to display different messages based on something the user inputs, you would use if/else logic. In our above example, we can display different things based on the age the user entered by changing our display.html to:

<?
    if($age>50);
        echo "Hi $name, you are ancient!<p>";
    elseif($age>30);
        echo "Hi $name, you are very old!<p>";
    else;
        echo "Hi $name.";
    endif;
>

PHP/FI provides a very powerful scripting language which will do much more than what the above simple example demonstrates. See the section on the PHP/FI Script Language for more information.

You can also use PHP/FI to configure who is allowed to access your pages. This is done using a built-in configuration screen. With this you could for example specify that only people from certain domains would be allowed to see your pages, or you could create a rule which would password protect certain pages. See the Access Control section for more details.

PHP/FI is also capable of receiving file uploads from any RFC-1867 compliant web browser. This feature lets people upload both text and binary files. With PHP/FI's access control and logical functions, you have full control over who is allowed to upload and what is to be done with the file once it has been uploaded. See the File Upload section for more details.

PHP/FI has support for a database package called mSQL. This allows you to put information into a database and access this information through simple embedded SQL queries right in your .HTML files. Adding a database back-end to a web page has never been easier. See the section on mSQL Support for more information.

PHP/FI has support for the Postgres95/PostgreSQL database package. It supports embedded SQL queries in your .HTML files. See the section on Postgres95/PostgreSQL Support for more information.

PHP/FI also has support for the mysql database package. It supports embedded SQL queries in your .HTML files. See the section on mysql Support for more information.


CGI Redirection

Apache 1.0.x Notes

A good way to run PHP/FI is by using a cgi redirection module with the Apache server. Please note that you do not need to worry about redirection modules if you are using the Apache module version of PHP/FI. There are two of these redirection modules available. One is developed by Dave Andersen <angio@aros.net> and it is available at ftp://ftp.aros.net/pub/util/apache/mod_cgi_redirect.c and the other comes bundled with Apache and is called mod_actions.c. The modules are extremely similar. They differ slightly in their usage. Both have been tested and both work with PHP/FI.

One large caveat at the time of this writing (Apr.20/96) is that the current official Apache release (1.0.5) has a severe limitation which prevents cgi redirected requests from having any post-method data associated with them. I have tracked this down and fixed it in my version of Apache, and there is an official patch available in the File Archives on the PHP Home Page.

A second rather large caveat with Apache 1.0.x is that it does not align double types correctly on most architectures. You find find yourself getting strange bus errors from your httpd when using mod_php, either upgrade to Apache 1.1 or edit the alloc.c Apache source file. In this file you will find the following piece of code:

  union align
  {
    /* Types which are likely to have the longest RELEVANT alignment
     * restrictions... we don't do much with doubles.
     */

    char *cp;
    void (*f)();
    long l;
    FILE *fp;
  };

You will need to add a double to this line and recompile your Apache server. The correct block of code is:

  union align
  {
    /* Types which are likely to have the longest RELEVANT alignment
     * restrictions... we don't do much with doubles.
     */

    char *cp;
    void (*f)();
    long l;
    FILE *fp;
    double d;
  };

Check the Apache documentation on how to add a module. Generally you add the module name to a file called Configuration. The line to be added if you want to use the mod_actions module is:

Module action_module mod_actions.o

If you are using the mod_cgi_redirect.c module add this line:

Module cgi_redirect_module mod_cgi_redirect.o

Then compile your httpd and install it. To configure the cgi redirection you need to either create a new mime type in your mime.types file or you can use the AddType command in your srm.conf file to add the mime type. The mime type to be added should be something like this:

application/x-httpd-php phtml

If you are using the mod_actions.c module you need to add the following line to your srm.conf file:

Action application/x-httpd-php /cgi-bin/php.cgi

If you are using mod_cgi_redirect.c you should add this line to srm.conf:

CgiRedirect application/x-httpd-php /cgi-bin/php.cgi

Don't try to use both mod_actions.c and mod_cgi_redirect.c at the same time.

Once you have one of these cgi redirection modules installed and configured correctly, you will be able to specify that you want a file parsed by php/fi simply by making the file's extension .phtml. Furthermore, if you add index.phtml to your DirectoryIndex configuration line in your srm.conf file then the top-level page in a directory will be automatically parsed by php if your index file is called index.phtml.

Netscape HTTPD

You can automatically redirect requests for files with a given extension to be handled by PHP/FI by using the Netscape Server CGI Redirection module. This module is available in the File Archives on the PHP/FI Home Page. The README in the package explicitly explains how to configure it for use with PHP/FI.

NCSA HTTPD

NCSA does not currently support modules, so in order to do cgi redirection with this server you need to modify your server source code. A patch to do this with NCSA 1.5 is available in the PHP/FI file archives.


Security Issues

The CGI version of PHP/FI does not read any .htaccess files which may be present in a directory. This means that if you have files that are protected using the standard .htaccess server-based access control feature, people could potentially circumvent this security by loading the page through PHP/FI. Note that this is not an issue for the Apache module version of PHP/FI.

A second problem with the CGI version is that if it is placed in the system's cgi-bin directory it can be used to view any file on your system as long as the user id it runs as has access to it.

There are a couple of different solutions to this problem. The easiest is probably to use the PATTERN_RESTRICT feature found in php.h. This lets you define an extension (or a pattern of extensions) which are allowed to be parsed by PHP/FI. If a file does not have this extension and someone tries to load it with PHP/FI, an access denied message will appear.

Another solution is to use the PHP/FI access control mechanism to mimic the access control setup you have in your .htaccess file. Keeping this information in two places can be tedious though, and the two systems don't share all of the same features.

The problem can also be solved using file permissions. PHP/FI can be set up to run setuid as any user you wish. Then files that are to be read by PHP/FI can be given appropriate permissions and files not to be read by PHP/FI should be owned by another user id and have their permissions changed accordingly.

For additional security options related to sites which provide shared access to PHP, see the Safe Mode section.


Safe Mode

PHP's Safe Mode tries to solve the common problem faced by many ISP's regarding letting all their users run CGI programs. The common mechanism for making shared CGI access more secure is to use a cgi wrapper like the su_exec utility that comes with Apache. This will not work for PHP when it is running as a module because it is not a separate process that can be setuid'ed.

It is based on a file permission scheme. Simply put, if a file is either owned by the same user id as the script that is trying to access it, or if the file is in a directory that is owned by the same user as the script that is trying to access it, then the access is allowed. One caveat here is that you must make sure that your OS does not allow non-root user to chown away the ownership on one of their files. Many older SysV systems allow this. The most common one is Irix. It is possible to change this behaviour at the OS level on Irix.

Safe Mode applies to each function which could possibly be a security risk. Below is the current list of checks applied to each relevant function. In the following list, PHP UID refers to the user id of the owner of the current file being parsed by PHP, and HTTP UID refers to the user id the httpd process is running as (usually nobody).

Include, ReadFile, Fopen, File, Link, Unlink, Symlink, Rename, RmDir, ChMod, ChOwn, ChGrp
Owner of file to be included must either be the PHP UID or the directory in which the file resides must be owned by the PHP UID.
Exec, System, PassThru and Popen
Executables to be forked and executed must reside in the directory defined by the PHP_SAFE_MODE_EXEC_DIR #define in php.h when PHP is compiled.
Mysql_Connect
This function takes an optional username to use to connect to an MySQL database. When in safe mode, this username must either be the username of the owner of the current file being parsed, or the name of the httpd user (usually nobody).
HTTP Authentication
The numerical user id of the owner of the script containing the HTTP Authentication code will be prepended to the authentication realm. This is to prevent someone from writing a password grabbing script which spoofs another authenticated page on the same server.


Running PHP/FI from the command line

If you build the CGI version of PHP/FI, you can use it from the command line simply typing: php.cgi filename where filename is the file you want to parse. You can also create standalone PHP/FI scripts by making the first line of your script look something like:

    #!/usr/local/bin/php.cgi -q
The "-q" suppresses the printing of the HTTP headers. You can leave off this option if you like.


HTTP Authentication

The HTTP Authentication hooks in PHP/FI are only available when it is running as an Apache module. In an Apache module PHP/FI script, it is possible to use the Header() command to send an "Authentication Required" message to the client browser causing it to pop up a Username/Password input window. Once the user has filled in a username and a password, the URL containing the PHP/FI script will be called again with the variables, $PHP_AUTH_USER, $PHP_AUTH_PW and $PHP_AUTH_TYPE set to the user name, password and authentication type respectively. Only "Basic" authentication is supported at this point.

An example script fragment which would force client authentication on a page would be the following:

    <?
        if(!$PHP_AUTH_USER) {
            Header("WWW-authenticate: basic realm=\"My Realm\"");
            Header("HTTP/1.0 401 Unauthorized");
			echo "Text to send if user hits Cancel button\n"
            exit;
        } else {
            echo "Hello $PHP_AUTH_USER.<P>";
            echo "You entered $PHP_AUTH_PW as your password.<P>";
        }
    >

Instead of simply printing out the $PHP_AUTH_USER and $PHP_AUTH_PW, you would probably want to check the username and password for validity. Perhaps by sending a query to a database, or by looking up the user in a dbm file.

Watch out for buggy Internet Explorer browsers out there. They seem very picky about the order of the headers. Sending the WWW-authenticate header before the HTTP/1.0 401 header seems to do the trick for now.

In order to prevent someone from writing a script which reveals the password for a page that was authenticated through a traditional external mechanism, the PHP_AUTH variables will not be set if external authentication is enabled for that particular page.

Note however that the above does not prevent someone who controls a non-authenticated URL from stealing passwords from authenticated URL's on the same server. The PHP_AUTH_VARS define in php.h can be undefined to make sure that these variables will never be set and thus disable anybody from using mod_php to try to steal passwords.


Apache Request Variables

When running PHP as an Apache module, you may access the request header variables sent by the remote browser by prepending $req_ to the beginning of the header value you would like to use. The phpinfo() function can be used to display all the request headers.

eg.

    <
        echo "$req_connection
"; echo "$req_host
"; >
The above simple script might output:
    Keep-Alive
    www.host.com

Apache Module Notes

Running PHP/FI as an Apache module is the most efficient way of using the package. Running it as a module means that the PHP/FI functionality is combined with the Apache server's functionality in a single program. There are a number of advantages to running it as a module:

Performance

Performance-wise it is a lot faster than traditional CGI programs. In fact, when running PHP/FI as a module, there is no CGI involved. The script code in the HTML files is executed directly by the Apache web server process.

Security

When running as a module, the normal httpd-based access restriction rules defined either in the Apache conf files or in private .htaccess files are first applied before the module is allowed to parse the file. Alternatively, you can also create PHP/FI scripts that control the normal httpd-based authentication. See HTTP Authentication.

Configurability

Since the parser is always active inside the httpd process, it can be configured on startup using the same configuration files used to configure the httpd process. The module can even be configured on a per-directory basis by placing the PHP configuration directives in the .htaccess files.

Basis for custom server-based function

For C programmers interested in accessing their functions from within Apache, the PHP/FI framework provides a very simple interface to Apache and to PHP itself. It is much easier to add a function to PHP and call that from a parsed page than it is to write an entire Apache module from scratch. See the Adding your own internal functions to PHP/FI sections at the end of this document for further details.

Apache Module Configuration Directives

The following directives can be placed either in the srm.conf file, or within <Directory>...</Directory> tags in access.conf or in <Location /path>...</Location> tags in access.conf or in individual .htaccess files. In order for the directives to work in .htaccess files, the Options override must be set on the AllowOverride Apache directive, with the exception of the phpEngine directive which is only available in the *.conf files.

phpShowInfo on|off
Turn the PHP info footers on or off. Default is on.

phpLogging on|off
Turn logging on or off. Default is on.

phpDebug on|off
Turn automatic ?info debug screen on or off. Default is off.

phpUploadTmpDir directory
Set the directory where form-uploaded files will be placed.

phpDbmLogDir directory
Set the directory where dbm-based logging files will be written.

phpSQLLogDB database
Set name of SQL database to use for logging. Default is "phpfi"

phpSQLLogHost hostname
Set hostname where SQL database to use for logging is found. Default is localhost.

phpAccessDir directory
Set the directory where PHP-internal access control files are stored.

phpMaxDataSpace KiloBytes
Max size a sub-pool can grow to within the PHP module. Setting this value to a low number will minimize the impact that mod_php will have on your system, but it may also limit people from writing complex scripts. The default is 8K.

phpIncludePath colon-separated path
A colon-separated list of directories where php will look for files in when running include(). The default is to look only in the current directory.
phpEngine on|off
Turn the PHP parsing engine on or off. The default is on and this directive is only useful for sites that wish to allow directives from the AllowOverride Options list of directives to function in .htaccess files while at the same time restricting mod_php access. The common way to handle per-virtual host php installs is to enable the PHP mime type with an AddType directive on a per virtual host basis and then put "e;phpEngine off" in the non-PHP virtual host blocks. If a non PHP customer tries to circumvent things by placing the PHP mime type in their .htaccess, the phpEngine off setting restricts the PHP parser from functioning.

All of these directives are optional. If a directive is not specified anywhere, the compile-time default will be used.


FastCGI Support

PHP/FI can be compiled with FastCGI support. You will need fetch and compile FCGI Development Kit for your platform before compiling PHP/FI. You will also need to get CGI Redirection working. Then follow the instructions in the FastCGI documentation for configuring FastCGI for your platform. If you are using the mod_fastcgi module with the Apache server, here are the step-by-step instructions:

Now, any pages with the .fhtml extension will be handed off to the FastCGI php.fcgi process which is already running. The php.fcgi binary will still work as a normal CGI binary, so you could just create a symbolic link from php.cgi to php.fcgi.

If you are not using Apache, the above steps will be similar, but not identical. CGI Redirection mechanisms are available for NCSA and Netscape servers at the PHP/FI File Archive.


Access Control

Note that the built-in PHP/FI based access control is likely to be discontinued in future versions. You should seriously consider using the security mechanism that comes with your web server instead.

If you chose to include access control when you compiled the package, you may append ?config to any URL to edit the access control file. ie.

http://your.machine.domain/cgi-bin/php.cgi/path/file.html?config

Your configuration password will initially be set to your user id. If your user id does not work as your password, it probably means that PHP could not read the /etc/passwd file to locate your user id. If this is the case, the initial password will be set to "php". It is a good idea to change this password. Note that multiple users may maintain their own personal configuration files through a single PHP/FI binary.

Access Control can be quite confusing initially. The ?config screen is divided up into a number of sections. The top section is for changing the password used to make sure that only people who know this password can change access control characteristics. In a system-wide installation, each user has his or her own configuration screen with his or her own password.

The second section of the ?config screen consists of a number of tables. Each table defines a rule-set. The first rule-set is always the default rule-set. This default rule-set is used if a page does not have a rule-set defined specifically for it. After the default rule-set, any number of specific rule-set tables will follow.

To add a rule-set for a specific file, enter the URL of the file in your browser and add ?config to the end of the URL. On the ?config screen that comes up you will see that a rule-set has been added for this page, if it wasn't already there. When a new rule-set is added, it is initially set to be the same as the default rule-set. The following picture shows two simple rule-sets. First a default rule-set which just indicates that hits from all domains should be logged, and second, for the file /~rasmus/test.html and only that file, any users coming from a ".edu" domain will not be granted access.

[Image of ?config screen]

To edit a rule-set modify the fields until the desired configuration is reached within a rule-set and then hit the "Submit Changes" button. If more rules are needed, hit the "Add Rule" button and then edit the added rule.

To delete a rule, select the checkbox to the right of the rule and hit the "Submit Changes" button. The screen will redraw and the rule should disappear.

Note that you need to enter a regular expression in the pattern field. See the section on regular expressions in this documentation for more details.


Access Logging

Access Logging is another optional feature which can be enabled at compile-time by answering Yes to the question in the install script. You may either store your access log data in dbm files, in an mSQL database, or in an mysql database. The latter two are more powerful, but is also a bit more difficult to set up.

To use dbm files for storing your access logs, you will need to specify a directory in which log files can be written. PHP will try to create this directory if it doesn't exist, but to make sure it has the proper permissions, you may want to create this directory yourself before running PHP for the first time. The permissions on the directory should be such that the user id under which the PHP cgi program will run can write to the directory.

To use an mSQL or mysql database for storing your access log data, you need to first make sure you have mSQL or mysql installed and running on your system. Then you need to create a database. The default name is "phpfi" although this can be changed in src/php.h. To create this database for mSQL, type:

    msqladmin create phpfi

or for mysql type:

    mysqladmin create phpfi

Then for mSQL, edit your msql.acl file and make sure the permissions on the database are correct. Something like the following should suffice:

    database=phpfi
    read=*
    write=nobody,<your user id>
    access=local

For mysql, you need to make sure the httpd user (usually "nobody") has access to the database. Unlike mSQL, mysql stores access control data in a database. Assuming default permissions, you should be able to simply execute the following command:

    echo "INSERT INTO user VALUES ('localhost','nobody','','Y','Y','Y','Y','Y','Y','Y','Y','Y');" | mysql mysql

Don't forget to load this new configuration with:

    mysqladmin reload

For each user id for whom you want to store log data, you need to create two tables. The msqllog shell script in the scripts directory will do this for you. Simply type:

    msqllog <user id> 

or for mysql, type:

    mysqllog <user id> 

and the script will create the appropriate tables. You may need to edit the script to make it reflect where things are stored on your system.

You may want to have a look at this script. It defines the field sizes of your log tables. If, for example, you know that your file paths exceed 64 characters, you need to bump up the filename size in both the logN and the lastN tables in this msqllog or mysqllog file.

Access logging stores information about each "hit" on a page. This information can then be summarized by examining these log files. An example log file summarizing script is included in the package. It is the log.html file in the examples directory. This is the dbm log file analyzer. The mSQL log file analyzer is called mlog.html. And the mysql log file analyzer is called mylog.html. To run it, copy it and the other mlog.* files to a directory accessible from your web server and type:

    http://your.machine.domain/cgi-bin/php.cgi/path/mlog.html

Or, if you are using the Apache module version, you can give the script a ".phtml" extension and call it with:

    http://your.machine.domain/path/mlog.phtml

By default, if you have compiled PHP with access logging enabled, then your pages will appear with a footer containing some access information. You may not want to see this footer, but still log hits. You can turn off this footer with a "phpShowInfo off" line in your Apache httpd.conf or .htaccess files if you are running Apache. If you are not running Apache, you may turn these log footers off either by creating a rule in the ?config section for the page, or by adding a tag like this to your page:

<?setshowinfo(0)>


Relative vs. Absolute URL's - or, Why do my Images Break?

A problem common to all CGI wrappers is that the HTTPD program changes the current directory to the directory where whatever it is loading is stored. In the case of a CGI program, the current directory is set to the directory where the CGI program resides. This is normally not a problem, except when it comes to relative URL's.

A relative URL is a URL which relies upon the current directory being the same as the directory where the current HTML file is located. So, for example, if I had the URL:

    http://my.machine/~rasmus/file.html

the actual HTML file might be:

    ~rasmus/public_html/file.html

If within the file.html file I had the tag:

    <IMG SRC="pic.gif">

when loaded normally this file gif file is expected to be in ~rasmus/public_html/pic.gif. However, when loaded through a CGI wrapper with a URL like:

    http://my.machine/cgi-bin/php.cgi/~rasmus/file.html

then HTTPD sets the current directory to /cgi-bin (or wherever the ScriptAlias might point) and subsequently when the page is loaded the pic.gif file is expected to be in: /cgi-bin/pic.gif which is usually not the desired effect.

The quick way around this problem is to use absolute URL's. In the above example if the image tag had been:

    <IMG SRC="/~rasmus/pic.gif">

then there would have been no problem. Using absolute URL's is not always desirable as it makes pages less portable. An obvious question you may have at this point is, "Why doesn't PHP just change the current directory to the right place?". The answer is that PHP actually does change the current directory to the location of the HTML file it is displaying. Any file paths used inside PHP Script tags, can be relative. The problem is that tags outside of PHP's control such as <img > and <a href > will not be passed through PHP. When they are parsed, PHP is no longer active and the current working directory has been set back to the directory specified by the HTTP Daemon.

The Solution is a compromise. PHP provides a variable called PATH_DIR. It contains the directory portion of the current HTML file at all times. If this PATH_DIR variable is used in the <img > and <a href > tags then the effect of a relative URL can be achieved, although to the server it will look like an absolute URL when parsed. From our above example, the only change we would need to make would be to change the img tag to:

    <IMG SRC="<?echo $PATH_DIR>/pic.gif">
By using the above, you can move the file containing this tag around, and the tag will always refer to a pic.gif file in the same directory as the source HTML file.

Another way to handle this is to use the traditional <BASE HREF=...> in the HTML file.


How PHP handles GET and POST method data

PHP will detect both GET and POST method data coming from HTML forms. One important point to understand is that POST method data is always treated first if both are present. If a PHP variable is defined by the POST method data, or if the variable is defined by the HTTP daemon in the Unix environment, then GET method data cannot overwrite it. This is to prevent somebody from adding ?REMOTE_HOST=some.bogus.host to their URL's and thus tricking the PHP logging mechanism into recording this alternate data. POST method data is however allowed to overwrite these variables.

Any component of the GET data (the data following a '?' in the URL) which is of the form, word=something will define the variable $word to contain the value something. Even if the data is not of this form, it can be accessed with the $argv built-in array. For example, in a URL like:

    /cgi-bin/php.cgi/file.html?abc+def+EMAIL_ADDR=rasmus@vex.net&var=value
The relevant components of the PHP symbol table will be:

    $argc       = 4
    $argv[0]    = abc
    $argv[1]    = def
    $argv[2]    = EMAIL_ADDR=rasmus@vex.net&var=value
    $EMAIL_ADDR = rasmus@vex.net
    $var        = value

Notice how the EMAIL_ADDR part of the data shows up both as $argv[2] where it is unparsed, and the $EMAIL_ADDR variable is created to contain rasmus@vex.net.

The $EMAIL_ADDR variable was used as an example in the above because it is a useful variable if you are using the logging features of PHP. By adding:

    ?EMAIL_ADDR=

to any links on a page where the user's email address is known, you may propagate it to the next page. The PHP logging system will automatically look for this variable and record its value as the user's e-mail address in the logs. For any users of PHP1, the above serves the same function as adding ?<!--$email--> to the URL used to do in PHP1. It looks a little bit more complex now, but it is also completely general allowing you to build your own complex pages.

In the above example you can also see how multiple variables can be defined right in the GET method data by separating each with the "&" character. This "&" separated list of variables must be the last (or only) component of the GET method data for it to be valid.

SELECT MULTIPLE and PHP

The SELECT MULTIPLE tag in an HTML construct allows users to select multiple items from a list. These items are then passed to the action handler for the form. The problem is that they are all passed with the same widget name. ie.

    <SELECT NAME="var" MULTIPLE>

Each selected option will arrive at the action handler as:

var=option1
var=option2
var=option3

Each option will overwrite the contents of the previous $var variable. The solution is to use PHP/FI's non-indexed array feature. The following should be used:

    <SELECT NAME="var[]" MULTIPLE>

This tells PHP/FI to treat var as an array an each assignment of a value to var[] adds an item to the array. The first item becomes $var[0], the next $var[1], etc. The count() function can be used to determine how many options were selected, and the sort() function can be used to sort the option array if necessary.


IMAGE SUBMIT and PHP

When submitting a form, it is possible to use an image instead of the standard submit button with a tag like:

    <input type=image src=image.gif name=sub>

When the user clicks somewhere on the image, the accompanying form will be transmitted to the server with two additional variables, sub_x and sub_y. These contain the coordinates of the user click within the image. The experienced may note that the actual variable names sent by the browser contains a period rather than an underscore, but PHP converts the period to an underscore automatically.


GD (a graphics library for GIF creation) Support in PHP

PHP supports the GD library version 1.2 written by Thomas Boutell. There is no GD code in PHP itself. If you wish to use the GD support in PHP/FI, you must obtain the GD library from http://www.boutell.com/gd/gd1.2.tar.Z, install it, and then re-install PHP.

Not all of the GD features are supported by PHP. For a list of supported functions see the Alphabetical List of Functions. All the GD functions start with the word, Image.

More information on the GD package is available at: http://www.boutell.com/gd/.

GD 1.2 is copyright 1994, 1995 Quest Protein Database Center, Cold Springs Harbor Labs.


PHP/FI and Virtual Hosts

PHP works fine on virtual host setups supported by some http daemons. The one problem that may occur on such a setup is related to an inconsistency in the way httpd sets the SCRIPT_NAME environment variable. Normally it is set to the path of the current CGI program in relation to the top-level ROOT_DIR on the httpd server. However, when a virtual domain is used, some httpd's do not correctly set the SCRIPT_NAME variable as the relative path from the virtual domain's top level directory as it should. If the ?config screen gives you an invalid URL error message, you know that this problem exists on your setup. You will need to edit the php.h file and set the VIRTUAL_PATH #define to the path to your php.cgi binary relative to your top-level directory.


File Upload Support

PHP/FI will automatically detect a file upload from a browser which supports the form-based file upload features as proposed by E. Nebel and L. Masinter from Xerox and described in RFC 1867.

A file upload screen can be built by creating a special form which looks something like this:

<FORM ENCTYPE="multipart/form-data" ACTION="_URL_" METHOD=POST>
<INPUT TYPE="hidden" name="MAX_FILE_SIZE" value="1000">
Send this file: <INPUT NAME="userfile" TYPE="file">
<INPUT TYPE="submit" VALUE="Send File">
</FORM>

The _URL_ should point to a php html file. The MAX_FILE_SIZE hidden field must precede the file input field and its value is the maximum filesize accepted. The value is in bytes. In this destination file, the following variables will be defined upon a successful upload:

$userfile

The temporary filename in which the uploaded file was stored on the server machine.

$userfile_name

The original name of the file on the sender's system.

$userfile_size

The size of the uploaded file in bytes.

$userfile_type

The mime type of the file if the browser provided this information. An example would be "image/gif".

The $userfile basename of the above variables will match the NAME field in the upload form.

Files will by default be stored in the server's default temporary directory. This can be changed by setting the environment variable TMPDIR in the environment in which PHP/FI runs. Setting it using a PutEnv() call from within a PHP/FI script will not work though. Alternatively, you may hard-code in a temporary directory by editing php.h and defining the UPLOAD_TMPDIR variable.

The PHP/FI script which receives the uploaded file should implement whatever logic is necessary for determining what should be done with the uploaded file. You can for example use the $file_size variable to throw away any files that are either too small or too big. You could use the $file_type variable to throw away any files that didn't match a certain type criteria. Whatever the logic, you should either delete the file from the temporary directory or move it elsewhere.

Please note that the CERN httpd seems to strip off everything starting at the first whitespace in the content-type mime header it gets from the client. As long as this is the case, CERN httpd will not support the file upload feature.


Cookie Support

PHP/FI transparently supports HTTP cookies as defined by Netscape's Spec. Cookies are a mechanism for storing data in the remote browser and thus tracking or identifying return users. You can set cookies using the SetCookie() function. Cookies are part of the HTTP header, so the SetCookie() function must be called before any output is sent to the browser. This is the same restriction as for the Header() function.

Any cookies sent to you from the client will automatically be turned into a PHP/FI variable just like GET and POST method data.

If you wish to assign multiple values to a single cookie, just add [] to the cookie name. For example:

    SetCookie("MyCookie[]","Rasmus Lerdorf", time()+3600);
Note that a cookie will replace a previous cookie by the same name in your browser unless the path or domain is different. So, for a shopping cart application you may want to keep a counter and pass this along. ie.

    
    $Count++;
    SetCookie("Count",$Count, time()+3600);
    SetCookie("Cart[$Count]",$item, time()+3600);

mSQL Support

mSQL stands for mini-SQL and is a small and simple SQL database engine written by David Hughes. It is available from ftp://ftp.bond.edu.au/pub/Minerva/msql

PHP/FI supports has a rich set of mSQL support functions:

msql()
msql_Close()
msql_Connect()
msql_CreateDB()
msql_dbName()
msql_DropDB()
msql_FieldFlags()
msql_FieldLen()
msql_FieldName()
msql_FieldType()
msql_FreeResult()
msql_ListDBs()
msql_Listfields()
msql_ListTables()
msql_NumFields()
msql_NumRows()
msql_RegCase()
msql_Result()
msql_TableName()

In addition to these functions, PHP/FI can also be compiled to automatically escape any forward single quote ( ' ) characters found in GET or POST data. If the MAGIC_QUOTES variable is defined in the php.h file then these quotes will be automatically escaped making it easier to pass form data directly to msql queries.


Postgres95/PostgreSQL Support

Postgres95/PostgreSQL is a powerful public domain database that implements a significant subset of the SQL language. It supports many datatypes and commands that are not available in mSQL. More information about Postgres and the software itself can be found at this URL: http://www.postgreSQL.org/.

The following PHP functions are available for Postgres95:

pg_Connect()
pg_Close()
pg_Host()
pg_Port()
pg_Options()
pg_tty()
pg_DBname()
pg_Exec()
pg_Result()
pg_FreeResult()
pg_GetLastOid()
pg_NumRows()
pg_NumFields()
pg_FieldNum()
pg_FieldName()
pg_FieldType()
pg_FieldSize()
pg_FieldPrtLen()
pg_errorMessage()

Note: Binary cursors are not supported.

In addition to these functions, PHP/FI can also be compiled to automatically escape any forward single quote ( ' ) and double quote ( " ) characters found in GET or POST data. If the MAGIC_QUOTES variable is defined in the php.h file then these quotes will be automatically escaped making it easier to pass form data directly to Postgres queries.

Here is a sample script that connects to Postgres database on localhost called 'mydb' and retrieves the names and ages of people in a table:

<?
   $conn = pg_Connect("localhost", "5432", "", "", "mydb");
   if (!$conn) {
      echo "An error occured.\n";
      exit;
   }

   $result = pg_Exec($conn, "select * from table1");
   if (!$result) {
      echo "An error occured.\n";
      exit;
   }

   $num = pg_NumRows($result);
   $i = 0;

   while ($i < $num) {
      echo "name: ";
      echo pg_Result($result, $i, "name");
      echo "  age: ";
      echo pg_Result($result, $i, "age");
      echo "<BR>";
      $i++;
   }

   pg_FreeResult($result);
   pg_Close($conn);
>


mysql Support

mysql is an clone of the mSQL package. You can get a copy from http://www.tcx.se/

PHP/FI supports has a rich set of mysql support functions:

mysql()
mysql_Close()
mysql_Connect()
mysql_CreateDB()
mysql_dbName()
mysql_DropDB()
mysql_FieldFlags()
mysql_FieldLen()
mysql_FieldName()
mysql_FieldType()
mysql_FreeResult()
mysql_ListDBs()
mysql_Listfields()
mysql_ListTables()
mysql_NumFields()
mysql_NumRows()
mysql_RegCase()
mysql_Result()
mysql_TableName()

In addition to these functions, PHP/FI can also be compiled to automatically escape any forward single quote ( ' ) characters found in GET or POST data. If the MAGIC_QUOTES variable is defined in the php.h file then these quotes will be automatically escaped making it easier to pass form data directly to mysql queries.


Solid Support

The Solid server is a high-volume SQL server. It supports the ANSI SQL2, ODBC, SAG CLI and X/Open SQL standards. More information about the Solid server is available at www.solidtech.com. The Solid interface to PHP was developed by DigiFace Internet Services.

The following PHP functions are available for the Solid Server:

Solid_Connect()
Solid_Close()
Solid_Exec()
Solid_Result()
Solid_FreeResult()
Solid_NumRows()
Solid_NumFields()
Solid_FieldNum()
Solid_FieldName()

In addition to these functions, PHP/FI can also be compiled to automatically escape any forward single quote ( ' ) characters found in GET or POST data. If the MAGIC_QUOTES variable is defined in the php.h file then these quotes will be automatically escaped making it easier to pass form data directly to Solid queries.

Here is the same script that was shown in the Postgres section, adapted for the Solid server.

<?
   $conn = Solid_Connect("", "username", "password");
   if (!$conn) {
      echo "An error occured.\n";
      exit;
   }

   $result = Solid_Exec($conn, "select * from table1");
   if (!$result) {
      echo "An error occured.\n";
      exit;
   }

   while (Solid_FetchRow($result)) {
      echo "name: ";
      echo Solid_Result($result, "name");
      echo "  age: ";
      echo Solid_Result($result, "age");
      echo "<BR>";
   }

   Solid_FreeResult($result);
   Solid_Close($conn);
>


Sybase Support

The supporting functions uses Sybase DB library API calls. Therefore you must have sybase API libraries and headers files installed in your system in order to compile PHP/FI with sybase support.

The following PHP/FI functions are available for Sybase.

SybSQL_Connect()
SybSQL_DBuse()
SybSQL_Fieldname()
SybSQL_GetField()
SybSQL_IsRow()
SybSQL_NextRow()
SybSQL_NumFields()
SybSQL_NumRows()
SybSQL_Query()
SybSQL_Result()
SybSQL_Result_All()
SybSQL_Seek()

For a complete example, see the example following the sybSQL_Result() function.


Oracle Support

The PHP/FI interface to Oracle uses the Oracle Call Interface (OCI). You need the OCI libraries on your system to compile PHP/FI with Oracle support.

The following PHP/FI functions are available for Oracle:

Ora_Close()
Ora_Commit()
Ora_CommitOff()
Ora_CommitOn()
Ora_Exec()
Ora_Fetch()
Ora_GetColumn()
Ora_Logoff()
Ora_Logon()
Ora_Open()
Ora_Parse()
Ora_Rollback()

An example PHP/FI Oracle application:

<?
PutEnv("ORACLE_SID", "database");

$conn = Ora_Logon("username", "password");

if ($conn < 0) {
    echo("Could not connect to Oracle.\n");
    exit;
}

$cursor = Ora_Open($conn);

if ($cursor < 0) {
    echo("Could not open a cursor.\n");
    Ora_Logoff($conn);
    exit;
}

Ora_CommitOff($cursor);

if (Ora_Parse($cursor, "SELECT * FROM students") < 0) {
    echo("Parse failed!\n");
    Ora_Logoff($conn);
    exit;
}

$ncols = Ora_Exec($cursor);
$err = Ora_Fetch($cursor);
while ($err == 1) {
    $i = 0;
    while ($i < $ncol) {
        $col = Ora_GetColumn($cursor, $i);
        echo("got: $col (" + GetType($col) + ")\n");
        $i++;
    }
    $err = Ora_Fetch($cursor);
}

Ora_Close($cursor);
Ora_Logoff($conn);
>


Regular Expressions

Regular expressions are used for complex string manipulation in PHP/FI. The script interface to the regular expression support is through the following functions: EReg(), ERegi(), EReg_Replace(), ERegi_Replace(), Reg_Match(), Reg_Replace(), and Reg_Search(). The first argument to all three functions is a regular expression string. The EReg functions use the Posix Extended regular expressions as defined by POSIX 1003.2, while the Reg functions implement Basic regular expressions. For a complete description of regular expressions see your regex(7) man page. If you do not have this page, the regex(7) man page written by Henry Spencer can be found in the src/regex directory in the PHP/FI distribution. Ask your system administrator to install this man page for you.

Some examples of regular expressions and what they do:

ereg("abc",$string);
Returns true if "abc" is found anywhere in $string.

ereg("^abc",$string);
Returns true if "abc" is found at the beginning of $string.

ereg("abc$",$string);
Returns true if "abc" is found at the end of $string.

eregi("(ozilla.[23]|MSIE.3)",$HTTP_USER_AGENT);
Returns true if client browser is Netscape 2, 3 or MSIE 3.

ereg("([[:alnum:]]+) ([[:alnum:]]+) ([[:alnum:]]+)",$string,$regs);
Places three space separated words into $regs[1], $regs[2] and $regs[3].

ereg_replace("^","<BR>",$string)
Put a <BR> tag at the beginning of $string.

ereg_replace("$","<BR>",$string)
Put a <BR> tag at the end of $string.

ereg_replace(10,"",$string);
Get rid of any linefeed characters in $string.

ereg_replace(13,"<BR>",$string);
Replace all carriage returns with a <BR> tag in $string.


Escape Characters

The following escape sequences are supported in most places where a quoted string argument is used:

	\a --> bell
	\b --> backspace
	\n --> linefeed
	\r --> carriage return
	\t --> tab
	\nnn --> octal char
	\xXX --> hex char


Octal Notation of Unix file permissions

A couple of functions in the PHP/FI script language epxect octal arguments to denote Unix-style permission parameters. In this octal notation 3 bits are used to represent the values 0-7. Each bit of the three represents a specific permission. Octal is traditionally noted in some contexts by a leading 0, such as 0755. You do not need to use this leading 0 in PHP since the functions that expect octal parameters are will simplyassume that the parameter is octal. Using the leading 0 is however good practise to remind yourself that you are no longer dealing with a base 10 value.

Bit Description

    xxx
    ^^^
    ||+----1 bit (execute permission)
    |+-----2 bit (write permission)
    +------4 bit (read permission)
These three bits are repeated three times for owner, group, and world. Thus 0755 means:
    owner: r,w,x
    group: r, ,x
    world: r, ,x
Note that the execute bit on a directory means 'access', not 'execute'. There are also the extended bits in the fourth octal nibble, like 0?755:
    4: suid bit   (set userid)
    2: sgid bit   (set group id)
    1: sticky bit (on a directory, only the owner can delete a file)


PHP/FI Script Language

The PHP script language is similar in syntax to the C language in many ways. It supports variables, arrays, function calls, different variable types and most things you might need to write complex cgi programs.

Each PHP/FI function is described in the following section and can be quickly found by simply appending #function_name to the url for this document since each function description has been tagged with its name.

Syntax

Each PHP instruction starts with <? and ends with a >. Or, instructions may be grouped inside a single <? > pair and separated by ; characters.

Variables are supported and are indicated by preceding the variable name with a $. So, for example, to set a variable to 5 and then display this variable, the following is valid:

	<?$a = 5>
	<?echo $a>

This is the same as writing:

	<?; $a = 5; echo $a >

Or even:

	<?;
	$a = 5;
	echo $a;
	>

Extra white space characters such as spaces, tabs and new-lines are ignored. This fact should be used to format the PHP script blocks to make them easier to read. Case is relevant in variable names, but not in function calls. In the functional overview later on in this documentation, case is only used to make the function names easier to read. In the actual script language you can use any case you wish.

Comments are supported. A comment is written just like comments in the C language. /* starts a comment and */ ends a comment. Comments can be placed anywhere within the <? ... > block.


Variables

Three types of variables are supported. Long integer, Double precision floating point and character strings. They are automatically detected. For example:

	<?$a = 5>

causes $a to become a variable of type INTEGER.

	<?$a = 5.0>

causes $a to become a variable of type DOUBLE.

	<?$a = "5">

causes $a to become a variable of type STRING.

The type of the variable is not generally important. Every variable regardless of its type is converted to all three types internally and the various functions will try to use the correct type. There are only a few functions affected by the type of the variable.

All three variable types may also be treated as arrays by appending [value] to their names. Unlike C, these are actually associative arrays similar to those used in Perl. The following would be valid:

	<?
	  $a[0] = 5;
	  $a["hello"] = 6;
	  echo $a[0];
	  echo $a["hello"];
	>

Note that if a variable is used both as an array and as a normal variable, the normal variable is synonymous with the index "0" entry in the array. ie.

    $a = 1;

Is the same as writing:

    $a[0] = 1;

PHP/FI also supports non-indexed arrays. A non-indexed array will generate its own index as items are added to it. For example:

    $a[] = "Hello";
    $a[] = "There";

The first item inserted into a non-indexed array always gets assigned index 0, the second index 1, etc. Therefore the above items may be printed out with:

    echo $a[0];
    echo $a[1];
	

Arrays can be copied by a simple assignment. If $b is an array, then all the values can be copied to a new array named $a with:

    $a = $b;

Please not that if PHP does not force you to define variables before using them. If in the above statement, $b was undefined, then $a would be set to an empty string ("").

The [] notation is also used to indicate that arrays are to be appended. If $a and $b are both arrays, then $b can be appended to $a by:

    $a[] = $b;

In the above, there will be a difference between associative arrays and normal numbered arrays. Numbered arrays will be renumbered such that all elements from $b will come after the original elements from $a. While with associative arrays, elements in $b will be merged with elements in $a. Any elements (items with the same index name) which already exist in $a will be overwritten by $b elements.

You can use the count() function to determine the number of items in any array.

Also inherent to the language is the fact that the type of the variable determines how certain basic operations will be carried out. For example:

    $a = $b + $c;

can do a couple of different things. If $b is a number, the numerical value of $c is added to $b and the sum is stored in $a. In this case the type of $c is irrelevant. The operation is guided by the type of the first variable. If $b is a string, then the string value of $c is appended to $b and the resultant string is placed in $a. This also leads to some caveats. You should read the section on overloaded operators to get a better understanding of how to deal with them.


Associative Arrays

The previous section introduced associative arrays. An associative array is an array in which the index need not be a numerically sequential value. The array index can be any number or string. PHP/FI provides a set of functions to manipulate these associative arrays. These include, Next(), Prev(),Reset(),End(), and Key().


Variable Variables

Sometimes it is convenient to be able to have variable variable names. That is, a variable name which can be set and used dynamically. A normal variable is set with a statement such as:

    $a = "hello";

A variable variable takes the value of a variable and treats that as the name of a variable. In the above example, hello, can be used as the name of a variable by using two dollar signs. ie.

    $$a = "world";

At this point two variables have been defined and stored in the PHP/FI symbol tree:

    Variable Name        Variable Content
         a                   hello
         hello               world

Therefore, this statement:

    echo "$a $$a";

produces the exact same output as:

    echo "$a $hello";

ie. they both produce: hello world


Language Constructs

As far as language constructs are concerned, the PHP language is quite simple. The following commands are used to guide the control flow through a file:

The syntax of conditions are similar to that of the C language. == tests for equality. != means not equal. Also supported are: >, <, >=, <=. Conditional AND is &&, conditional OR is ||.

Examples:

    <?
      if($a==5 &&  $b!=0 );
        $c = 100 + $a / $b;
      endif;
    >

The above may also be written in standard C syntax:
In this case, there is no need for a semicolon after the closing curly brace.

    <?
      if($a==5 && $b!=0) {
          $c = 100 + $a / $b;
      }
    >

There is no difference between the two syntaxes. I personally like to use endif, endswitch and endwhile so I explicitly know which construct I am ending. However, these ending constructs can always be replaced with a closing curly brace.

It is important to note that the flow of the language is not dependent on the organization of the script blocks within the code. You can start an if expression in one block and have the end of the expression in another. For example:

	<?if($a==5 &&  $b!=0)>
		  <b>Normal html text</b>
	<?endif>

In this example it is easy to see why it is sometimes more desirable to use the endif keyword as opposed to a closing brace. The above is much more readable than the following:

	<?if($a==5 &&  $b!=0) {>
		  <b>Normal html text</b>
	<? } >

Both version are valid and they will do exactly the same thing.


User-Defined Functions

You may define a function within a PHP script with the following syntax:

    <?
      Function Test (
        echo "This is a test\n";
      );
    >

This function can now be called from anywhere in the script as long as the call comes after the function definition. A sample call might be:

    <?
      Test();
    >

User defined functions like this act exactly like PHP's internal functions in that you can pass arguments to them and have them return a value. Here is the syntax for a function definition of a function which takes 3 arguments and returns the sum of these arguments:

    <?
      Function Sum $a,$b,$c (
        return($a+$b+$c);
      );

      echo Sum($a,$b,$c);
    >

The return statement is used to return a value from the function. Only a single value can be returned using this mechanism, however, if more values need to be communicated back and forth between the main code and functions, global variables can be used. This brings us to the section on the scope of variables.


Scope of Variables

The scope of a variable is the context within which it is defined. For the most part all PHP/FI variables only have a single scope. However, within user-defined functions a local function scope is introduced. Any variable used inside a function is by default limited to the local function scope. For example:

    $a=1; /* global scope */
    Function Test (
      echo $a; /* reference to local scope variable */
    );
    Test();

This script will not produce any output because the echo statement refers to a local version of the $a variable, and it has not been assigned a value within this scope. You may notice that this is a little bit different from the C language in that global variables in C are automatically available to functions unless specifically overridden by a local definition. This can cause some problems in that people may inadvertently change a global variable. In PHP/FI global variables must be declared global inside a function if they are going to be used in that function. An example:

    $a=1;
    $b=2;
    Function Sum $first,$second (
      global $a,$b;

      $b = $a + $b;
    );
    Sum();
    echo $b;

The above script will output "3". By declaring $a and $b global within the function, all references to either variable will refer to the global version. There is no limit to the number of global variables that can be manipulated by a function. However, the variable must exist in the global scope prior to the function being called. You cannot create new global variables from within a function.

Another important feature of variable scoping is the static variable. A static variable exists only in a local function scope, but it does not lose its value when program execution leaves this scope. Consider the following example:

    Function Test (
      $a=0;
      echo $a;
      $a++;
    );

This function is quite useless since every time it is called it sets $a to 0 and prints "0". The $a++ which increments the variable serves no purpose since as soon as the function exits the $a variable disappears. To make a useful counting function which will not lose track of the current count, the $a variable is declared static:

    Function Test (
      static $a=0;
      echo $a;
      $a++;
    );

Now, every time the Test() function is called it will print the value of $a and increment it.

Static variables are also essential when functions are called recursively. A recursive function is one which calls itself. Care must be taken when writing a recursive function because it is possible to make it recurse indefinitely. You must make sure you have an adequate way of terminating the recursion. The following simple function recursively counts to 10:

    Function Test (
      static $count=0;

      $count++;
      echo $count;
      if($count <  10) {
        Test();
      } 
    );


Mathematical Expressions

PHP supports full mathematical operations anywhere an expression is expected. Order of operations are taken into account. The following are the valid operators:

	<? $a = 2 + 1 > Addition
	<? $a = 2 - 1 > Subtraction
	<? $a = 2 * 1 > Multiplication
	<? $a = 2 / 1 > Division
	<? $a = 2 % 1 > Modulus
	<? $a = 2 ^ 1 > Bit-wise Exclusive OR

Both bracketing and order of operations is supported, so the following is valid:

	<?$a = (2"+1")*3+6/3>

The C-like incremental operators += and -= are supported. ie.

    <? $a += $b>

This is equivalent to:

    <? $a = $a + $b>

The C-like bit-wise operators &=, |= and ^= are supported. ie.

    <? $a &= 4>
This is equivalent to:

    <? $a = $a &  4>


While Loops

You can loop within a PHP script by using the while(); endwhile; construct.

	<?
	  $a=0;
	  while($a<100) {
		  $a++;
		  echo $list[$a];	
	  } 
	>

The above example shows the use of a while loop to display the contents of an array. WARNING although the PHP language supports incremental operators such as ++ and -- to increment and decrement a variable, they are not treated exactly like they would be in the C language. The variable is incremented right away. There is no concept of incrementing the variable before or after the operation as there is in C.

As explained in the Language Constructs section above, the same can be obtained with while(); endwhile;.


Switch Construct

PHP supports a switch construct very similar to the C equivalent.

	<?
	  $a=0;
	  switch($a) {
		case 1;
		  echo "a is 1";
		  break;
		case "hello";
		  echo "a is hello";
		  break;
		default;
		  echo "a is unknown";
		  break;
	  } 
	>

The above is an example of a switch construct. It is similar to a series of if/elseif/else constructs but easier to read. The only difference between the PHP switch construct and that of the C language is that semi-colons are used to terminate every line. There are no colons.

As explained in the Language Constructs section above, the same can be obtained with switch(); endswitch;.

All of these constructs can of course be nested and used inside each other just like C. The various files in the examples directory of the PHP distribution should provide a good starting point for learning the language.


Secure Variables - Defeating GET method hacks

A previous section talked about GET and POST method data and variables. If you think about it, you may be able to envision a security issue. For example, if on a web page I have obtained some data from a database and I pass this data along in a variable called "data" in a POST method form. In the ensuing page I can access this variable and do something with it. However, if someone accessed this second page directly and put a "?data=something" right in the URL thereby doing a GET method variable set, they have effectively circumvented the original POST method form.

PHP provides a SecureVar() function which is used to mark variables names as being secure variables. These secure variables can only be set directly in a PHP script, or they can come from a POST method form. They cannot be set using the GET method variable definition mechanism. From our above scenario, if we placed the line:

    <?SecureVar("data")>

Near the beginning of our second page, then the GET method trick would not work. The "data" variable would appear to be empty unless it came directly from the POST method form on the first page.

The SecureVar() actually takes a regular expression as its argument, so you can mark patterns of variable names that should be treated in this secure manner. For example,

    <?SecureVar(".*data.*")>

Would mark any variable with the word "data" anywhere in their name as being secure.

Please note that POST-method forms are not intrinsically secure. People can emulate the posting of any data to a form by simply telnetting to the HTTP port on your system. You need to take appropriate security measures to stop people from doing this if in fact security is a concern.


Overloaded Operators and dealing with variable types

An overloaded operator is an operator like '+' for example which can do different things based on the types of the expressions it is asked to operate on.

The problem is that PHP understands 3 variable types. Integer, Double and String. When a variable is first assigned, PHP automatically figures out the variable type.

ie.

    $a = 1;     Type would be integer
    $b = 1.5;   Type would be double
    $c = "1";   Type would be string

Now, what happens when you do something like:

    $d = $a + $c;

The parser looks at the first part of the arithmetic expression and uses that to type the result and thus also the nature of the arithmetic that is to be done. In the above case since $a is an integer, $d will be an integer and an integer addition is done giving the result:

    $d = 2      Type is integer

Therefore:

    $d = $c + $a

Results in:

    $d = "11"   Type is string

The above makes sense to me, and once you understand it, it is probably workable. However, when more complex expressions are used it can get extremely confusing.

The solution is a simple type casting mechanism. In reality all variables are automatically converted to all 3 types, and an internal flag just marks what type the variable actually is. So, when I say:

    $a = 1;

Internally in the symbol table I store 3 versions.

    Integer:  1    <-- flag
    Double :  1.0
    String :  "1"

The SetType() function can move this flag indicating the type of the variable.

    SetType($a,"double");

This would force $a to be treated as a double from then on.

The GetType() function returns the type. GetType($a) would return "double" in this case.

Functions also exist to return the 3 various types without moving the type flag.

    IntVal($a)     returns  1
    DoubleVal($a)  returns  1.0
    StrVal($a)     returns  "1"

This doesn't change the overloaded operator nature of the PHP variables, but it does give you some tools to better deal with them. PHP is not not a full-fledged Perl look-alike. It has to be small and fast. Perl deals with the overloaded operator pitfall by forcing something like the '+' operator to only work on numbers. If you want to add strings, you must use the '.' operator. Once you start having separate operators for each type you start making the language much more complex. ie. you can't use '==' for stings, you now would use 'eq'. I don't see the point, especially for something like PHP where most of the scripts will be rather simple and in most cases written by non-programmers who want a language with a basic logical syntax that doesn't have too high a learning curve.


Suppressing Errors from function calls

It may be desirable in certain circumstances to ignore fatal errors which may be reported by specific PHP functions. For example, you may want to ignore errors from a dbmopen() call and simply check the return value of the call without having error messages appear on the web screen. This can be done by putting the "@" character in front of the function call. ie.

    $err_code = @dbmopen($filename,"w");

The actual error message that would have been printed can be checked by looking at the PHP internal variable, $phperrmsg.

A more general approach to suppress error message printing is to use the SetErrorReporting() function. With this function error printing can be disabled for entire blocks of code by preceding the block with a call like:

    SetErrorReporting(0);

This turns off all errors. They can then be re-enabled later with:

    SetErrorReporting(1);


Internal Functions

PHP has a number of built-in functions. Functions are called in the same manner as they are called in the C language. Some take one or more arguments, and some return values which can then be assigned to a variable or used as an argument to another function. For example:

	<?$t=time()>

This assigns the return value of the time() function to the t variable.

Alphabetical List of Functions

Abs(arg)

Abs returns the absolute value of arg.

AddSlashes(arg)

Escapes any $ \ or ' (if MAGIC_QUOTES is set) with a backslash. See also StripSlashes().

ASort(array)

Sort is used to sort a PHP associative array in ascending order. Unlike the Sort() function, ASort() maintains index-value pairings. It understands the three variable types and will sort alphabetically if the array contains strings, and numerically if the array contains numbers. In the case of an array which contains a mixture of types, the first type in the array will specify the sort method. Note that if you are going to sort a non-associative array, you should use the Sort() function.

BinDec(binary_string)

BinDec returns the decimal equivalent of the binary number represented by the binary_string argument. The largest number that can be converted is 31 bits long or 4294967295 in decimal. See also the DecBin() function.

ChDir(dir)

ChDir changes the current working directory to the directory specified in the argument.

ChGrp(file,group)

ChGrp changes the group id of the specified file.

ChMod(file,perms)

ChMod changes the file permissions of the specified file. The perms parameter must be specified in octal notation. eg. ChMod($filename,0755)

ChOwn(file,owner)

ChOwn changes the specified file to be owned by the specified owner. Note that this will only work if the PHP/FI binary is running as root (which is not generally a good idea).

Chop(string)

Chop removes all trailing whitespaces including new-lines, tabs and spaces and returns the new string.

Chr(arg)

Chr returns the ASCII character represented by the integer argument.

ClearStack()

The ClearStack() function is a hack/workaround for a deficiency in the PHP parser. This dificiency is that PHP only has a single expression stack. When inside a user-defined function this expression stack is never cleared because its contents may be needed within a complex expression in the context from which the user-defined function was called. This means that if you have a while loop with a lot of iterations inside an user-defined function, you may be chewing up a lot of stack space. You may even be hitting the max data space limit. You can put a call to ClearStack() inside your while loop to prevent this memory consumption, but the trade-off is that you cannot use your function within any sort of context. ie. you have to assign the output of the function to a temporary variable and then use this temporary variable in whatever context you need.

ClearStatCache()

The stat() system call is normally an expensive operation on most operating systems. In order to make sure that repeated calls to the various File* functions like FilePerms(), FileInode(), etc. the result of the last stat() call is always cached. If one of the File* functions is called again with the same argument, the cached stat() result will be used. In order to force a new stat() system call this ClearStatCache() function may be called to clear the cached stat() result.

closeDir()

closeDir closes a directory opened using the openDir function.

CloseLog()

CloseLog() closes the descriptor Syslog() uses to write to the system logger. See the closelog(3) UNIX man page for more details. See also Syslog(), OpenLog() and InitSyslog().

Cos(arg)

Cos returns the cosine of arg in radians. See also Sin() and Tan()

Count(array)

Count returns the number of items in an array variable. If the variable is not an array, the return value will be 1 (because a normal variable is similar to an array with only one item). If the variable is not defined, the return value will be 0.

Crypt(string,[salt])

Crypt will encrypt a string using the standard Unix DES encryption method. Arguments are a string to be encrypted and an optional two-character salt string to base the encryption on. See the Unix man page for your crypt function for more information. If you do not have a crypt function on your Unix system, you can use Michael Glad's public domain UFC-Crypt package which was developed in Denmark and hence not restricted by US export laws as long as you ftp it from an non-US site.

Date(format,time)

The Date function is used to display times and dates in various ways. The function takes a format string and a time as arguments. If the time argument is left off, the current time and date will be used. The time argument is specified as an integer in number of seconds since the Unix Epoch on Jan.1 1970. The format string is used to indicate which date/time components should be displayed and how they should be formatted. The following characters are recognized within the format string. Any unrecognized character is printed verbosely:

See also the MkTime() function.

dbList()

dbList outputs information about the db support compiled into PHP.

dbmClose(filename)

dbmClose simply closes the specified dbm file. It will also unlock any lock files, so it is important to close any dbm files that have been opened.

dbmDelete(filename,key)

dbmDelete will delete the key/content pair specified by the given key argument.

dbmExists(filename,key)

dbmExists will return 1 if the key exists and 0 otherwise.

dbmFetch(filename,key)

dbmFetch will return the content string associated with the given key.

dbmFirstKey(filename)

dbmFirstKey returns the first key in the dbm file. Note that no particular order is guaranteed since the order depends on hash table values calculated within the dbm implementation. You may use the Sort function to sort arrays of data from the dbm file if necessary.

dbmInsert(filename,key,content)

dbmInsert inserts a new key/content data pair into a dbm file. If the key already exists, the insert will fail.

dbmNextKey(filename,key)

dbmNextKey returns the next key after the specified key. By calling dbmfirstkey() followed by successive calls to dbmnextkey() it is possible to visit every key/content pair in the dbm file.

dbmOpen(filename,mode)

dbmOpen() opens a dbm file. The first argument is the full-path filename of the dbm file to be opened and the second is the file open mode which is one of "r", "n" or "w" for read, new (implies write) and write respectively. If ndbm support is used, ndbm will actually create filename.dir and filename.pag files. gdbm only uses one file, as does the internal flat ascii file support, and Berkeley's libdb create a filename.db file. Note that PHP does its own file locking in addition to any file locking that may be done by the dbm library itself. PHP does not delete the .lck files it creates. It uses these files simply as fixed inodes on which to do the file locking. For more information on dbm files, see your Unix man pages, or obtain GNU's gdbm from ftp://prep.ai.mit.edu/pub/gnu.

dbmReplace(filename,key,content)

dbmReplace is similar to the dbminsert() function, the only difference being that if the key already exists, the old content string will be replaced with the new.

DecBin(number)

DecBin returns a string containing a binary representation of the given number argument. The largest number that can be converted is 31 bits long or 4294967295 in decimal. See also the BinDec() function.

DecHex(number)

DecHex converts a decimal number to a hexadecimal string. See also the HexDec() function.

DecOct(number)

DecOct converts a decimal number to an octal number. See also OctDec().

doubleval(variable)

doubleval returns the double (floating point) value of the variable. See also the strval() and intval() functions.

Echo [format_string] expression [, expression [,...]]

Echo is not a function. ie. you do not put brackets around the arguments to it. It is used to display results of PHP functions or PHP variables. See the Escape Character Section for a list of special characters supported. The format_string is optional and if not present, no output formatting will be done. The format string is similar to the format string of the C printf function. See the man page for printf for more details. Up to 5 expressions can be printed with a single echo command. If you try to print more you will get a parser error. Note that the types of the expressions are not relevant. The expressions are automagically converted to the appropriate types as specified by the format string if one is present. If you want to format something and assign the formatted string to a variable instead of displaying it, use the sprintf() function.

The following conversions are supported,

%d %i
Print a signed decimal number.
%o
Print an ocal number.
%u
Print an unsigned decimal number.
%x %X
Print a hexadecimal number.
%f
Print a floating-point number.
%e %E
Print a floating-point number in scientific notation.
%g %G
Print a floating-point number in scientific notation or normal notation, as appropriate.
%c
Print a single character.
%s
Print a string of characters.
%%
Print a literal percent-sign.

The following flags are accepted.

'-'
Left-justify the output within the field-width.
'+'
Ensure that all integers are signed (with a plus/minus sign).
' '
Similar to '+', but uses a space instead of a plus-sign.
'#'
Print prefixes in front of hex and octal numbers designating them as such.
'''
Separate the digits into groups (usually comma-separated groups of three).
'0'
Pad the field-width with zeros.

All of these flags are dependent upon whether or not your C library's printf function supports them (the ''', for example, is a GNU extension).

Most conversions will accept a field width and a precision, as shown in the demo_echo.html file in the directory /examples. It is not necessary to specify any type modifiers, and, in fact, PHP will complain if the type modifier does not make sense (which is almost always the case). PHP will complain about (and refuse to accept) anything that it does not recognize. Any extra arguments given that are not required by the format-string are ignored.

End(variable)

End moves the internal array pointer for the given variable to the last item of the array and returns the value of this item. This is useful for traversing an associative array in reverse order. See also Reset() and Prev(). The following example would traverse an associative array in reverse order:

    <?
      Reset($array);
      $first_key = key($array);
      End($array);
      $k = key($array);
      while($k != $first_key);
        echo $array[$k];
        prev($array);
        $k = key($array);
      endwhile;
      echo $array[$k];
    >

ereg(expr,arg[,regs])

ereg returns non-zero if the regular expression is matched in the argument string. For example, the condition, <?if (ereg("^This.*", "This is an example string")> would be true since the "^This.*" expression says to match the word This at the beginning of the string and then match any characters afterwards. If the regs argument is present, then match registers are filled into positions 0-10 in the array named by the regs argument. Register 0 will always contain the full matched string. For more information on regular expressions, see the regular expression section of this document.

eregi(expr,arg[,regs])

eregi is identical to the ereg() function except for the fact that the regular expression is applied such that upper/lower case is ignored.

ereg_replace(expr,replace,arg)

ereg_Replace scans the entire argument string and replaces any portions of the string matched by the given expression with the replacement string. For example, in the string, "This is an example string" we could very easily replace every space with a dash with the command: ereg_replace(" ","-","This is an example string").For more information on regular expressions, see the regular expression section of this document.

eregi_replace(expr,replace,arg)

eregi_replace is identical to the ereg_replace() function except for the fact that the regular expression is applied such that upper/lower case is ignored.

EscapeShellCmd(string)

EscapeShellCmd escapes any characters in a string that might be used to trick a shell command into executing arbitrary commands. This function should be used to make sure that any data coming from user input is escaped before this data is passed to the Exec() or System() functions. A standard use would be:

    <?system(EscapeShellCmd($cmd))>

Eval(string)

Eval takes the contents of the string argument and treats it like a mini PHP/FI script. It will execute it as a separate PHP/FI script. Any variables set or accessed from inside the eval will be from the global reference frame in the current context of the eval statement in the script. Variable substitution is done on the string arguments, so if variables are to be used in the string expression they should be escaped. Some examples:

    $a = "echo phpversion();";
    eval($a);

    eval("echo phpversion();");

    eval("\$a=1; echo \$a;");

Exec(command_string [, array [,return_var]])

Exec executes the given unix command, however it does not output anything. It simply returns the last line from the result of the command. If you need to execute a command and have all the data from the command passed directly back without any interference, use the PassThru() function. If the array argument is present, then the specified array will be filled with every line of output from the unix command starting at the end of the array. Make sure you UnSet the array before the call if your array already contains elements and you want to start filling it at array element 0. If the return_var argument is present along with the array argument, then the return status of the executed unix command will be written to this variable. Note that if you are going to allow data coming from user input to be passed to this Exec function, then you should be using the EscapeShellCmd() function to make sure that users cannot trick the system into executing arbitrary commands. See also the system() function.

Exit

The Exit command is used to terminate parsing right away as soon as this tag is parsed.

Exp(arg)

Exp returns e raised to the power of arg. See also pow()

fclose($fd)

fclose() closes a file opened by fopen(). The argument is a file pointer index as returned by the fopen() call.

feof($fd)

Feof returns true if the file referred to by the file pointer index argument has hit end-of-file.

fgets($fd,bytes)

fgets() reads a line from a file opened by fopen(). Arguments are a file pointer index as returned by fopen() and the max number of bytes to read. Reading ends when max number of bytes have been read, or on an end of line. This is similar to the C fgets() call. See also fputs().

fgetss($fd,bytes)

Identical to the fgets() function, except this one tries to strip off any HTML tags or PHP/FI script tags as it is reading the file.

$array = File(filename)

File reads the entire file and returns an array with each array element containing a line of the file starting with array index 0.

fileAtime(filename)

fileAtime returns the time of last data access. If the file does not exist, or if it for some other reason could not be accessed, this function returns -1. If repeated calls to fileAtime and the rest ofthe file* functions are to be made and the file being accessed might change or disappear, the ClearStatCache() should be called before the call to the file* function.

fileCtime(filename)

fileCtime returns the time of last status change. If the file does not exist, or if it for some other reason could not be accessed, this function returns -1. If repeated calls to fileCtime and the rest ofthe file* functions are to be made and the file being accessed might change or disappear, the ClearStatCache() should be called before the call to the file* function.

fileGroup(filename)

fileGroup returns the group id of the owner of the file. If the file does not exist, or if it for some other reason could not be accessed, this function returns -1. If repeated calls to fileGroup and the rest ofthe file* functions are to be made and the file being accessed might change or disappear, the ClearStatCache() should be called before the call to the file* function.

fileInode(filename)

fileInode returns the file's inode. If the file does not exist, or if it for some other reason could not be accessed, this function returns -1. If repeated calls to fileInode and the rest ofthe file* functions are to be made and the file being accessed might change or disappear, the ClearStatCache() should be called before the call to the file* function.

fileMtime(filename)

fileMtime returns the time of last data modification. If the file does not exist, or if it for some other reason could not be accessed, this function returns -1. If repeated calls to fileMtime and the rest ofthe file* functions are to be made and the file being accessed might change or disappear, the ClearStatCache() should be called before the call to the file* function.

fileOwner(filename)

fileOwner returns the uid of the owner of the file. If the file does not exist, or if it for some other reason could not be accessed, this function returns -1. If repeated calls to fileOwner and the rest ofthe file* functions are to be made and the file being accessed might change or disappear, the ClearStatCache() should be called before the call to the file* function.

filePerms(filename)

filePerms returns the permission bits of the file. This is the st_mode field of the Unix C stat structure. If the file does not exist, or if it for some other reason could not be accessed, this function returns -1. If repeated calls to filePerms and the rest ofthe file* functions are to be made and the file being accessed might change or disappear, the ClearStatCache() should be called before the call to the file* function.

fileSize(filename)

fileSize returns the size of the file in bytes. If the file does not exist, or if it for some other reason could not be accessed, this function returns -1. If repeated calls to fileSize and the rest ofthe file* functions are to be made and the file being accessed might change or disappear, the ClearStatCache() should be called before the call to the file* function.

fileType(filename)

fileType returns the type of the file. The return values are one of: "dir", "file","fifo","char", "block", or "link". These are for, directory, regular file, fifo special, character special, block special and symbolic link, respectively.

Flush()

The Flush() function is used to Flush the output buffer. For the Apache module, it flushes Apache's output buffer, and for the CGI version it simply flushes stdout. When running as a CGI under Apache, the server will buffer the CGI script's output, so this Flush() function won't help much there. Look at running your script as an nph- script if you are running the CGI version of PHP under the Apache web server. Or, alternatively, run the Apache module version of PHP.

$fp = fopen(filename,mode)

fopen() opens a file and returns a file pointer index. If the file could not be opened the function returns -1. It is similar to the C fopen() call. The filename argument is the relative or absolute path to the file to be opened, and the mode argument is one of, "r", "r+", "w", "w+", "a", "a+". See the Unix man page on the fopen() call for more information. See also the popen() function description. See also the fclose() function description.

Example:

    $fp = fopen("/home/rasmus/file.txt","r");
fputs(fp,string)

fputs() writes a line to a file opened by fopen(). Arguments are a file pointer index as returned by fopen() and the string to write. Note that the string argument may contain the special escape characters, \n, \r and \t to output newlines, carriage returns and tabs respectively. See also fgets().

fseek(fp,pos)

fseek() positions a file pointer identified by the $fd argument which is the return value of the fopen() call. The file pointer is positioned at the beginning of the file plus the offset specified by the pos argument. See also ftell() and rewind().

fp = fsockopen(hostname,port)

fsockopen() opens a socket connection and returns a file pointer index. This file pointer index can be used by fgets, fputs and fclose. Arguments are a hostname and a port number. Return values are: -3 if the socket couldn't be created, -4 if the dns lookup on the hostname failed, -5 if the connection was refused or it timed out, -6 if the actual fdopen() call failed or -7 if the setvbuf() call failed. If the port number is 0, then the hostname argument will be treated as a filename of a Unix domain socket if your operating system support Unix domain sockets.

pos = ftell(fp)

ftell() returns the position of a file pointer identified by the fp argument which is the return value of the fopen() call. The position can later be used as an argument to fseek(). See also fseek() and rewind().

getAccDir()

getAccDir returns the directory where PHP access configuration files are kept. The access configuration filenames come from the numerical user id of the user whose access configurations they represent.

GetEnv(string)

GetEnv returns the value of the environment value specified by string. Normally this function is not used because environment variables are available to PHP/FI directly. If a reference is made to a variable which is not found in the internal symbol table, then the environment space is automatically searched. GetEnv should be used when it is necessary to ensure that an environment variable has not been overwritten by normal PHP/FI variable. Security mechanisms that rely on http server-defined variables like REMOTE_ADDR and REMOTE_HOST should load these variables using GetEnv as opposed to referencing them directly as $REMOTE_ADDR to avoid someone making up a fake form and posting the data to your server and thereby bypassing whatever security mechanism you might have.

getHostByName(domain_name)

getHostByName converts the given domain name into an IP address in nnn.nnn.nnn.nnn format.

getHostByAddr(ip_address)

getHostByAddr converts the given IP address in nnn.nnn.nnn.nnn format into a fully qualified domain name.

GetImageSize(filename)

The GetImageSize() function takes either a full path filename, or a relative path relative to the location of the calling script. It returns a 3 element array consisting of width, height and type. Width and height are in pixels, and a type of 1 means GIF, a 2 indicates a JPG file and a 3 indicates a PNG file. Other file types are not supported. The fourth element in the returned array is a string containing, "width=x height=y" that is suitable for using directly in an IMG tag. It is important to note that the GD image library is not needed to use this function. An example follows:

    <?
        $result = GetImageSize("img/flag.jpg");
    >
    <IMG SRC="img/flag.jpg" ?echo $result[3]> >

getLastAccess()

getLastAccess returns the date and time in unix time format of the last time the current page was access. This value can be passed to the Date() function for formatting.
This function is only available if PHP was compiled with Access Logging enabled.

getLastbrowser()

getLastBrowser returns the identification string of browser the last user to access the current page used.
This function is only available if PHP was compiled with Access Logging enabled.

getLastEmail()

getLastEmail returns the E-Mail address of the last user to access the current page.
This function is only available if PHP was compiled with Access Logging enabled.

getLastHost()

getLastHost returns the hostname of the last user to access the current page.
This function is only available if PHP was compiled with Access Logging enabled.

getLastMod()

getLastMod returns the date and time in unix time format of the last time the current page was modified. This value can be passed to the Date() function for formatting.
This function is only available if PHP was compiled with Access Logging enabled.

getLastref()

getLastRef returns the URL of the referring document of the last user to access the current page.
This function is only available if PHP was compiled with Access Logging enabled.

getLogDir()

getLogDir returns the top-level directory under which PHP log files can be found. The actual log files are in directories under this directory. Each subdirectory is the numerical user id of the user to whom the log files belong. Then within each directory a series of dbm log files are found, each with the numerical inode of the file they represent as the primary component of the filename.

getMyInode()

getMyInode returns the numerical inode of the current HTML file.

getMyPid()

getMyPid() returns the current process id of the PHP parsing process.

getMyUid()

getMyUid returns the numerical user id of the owner of the current HTML file.

getRandMax()

getRandMax returns the maximum random number the Rand function will return. If the value returned does not seem to be accurate, have a look in the php.h source file in the PHP distribution for more information.

getStartLogging()

getStartLogging returns the time and date in Unix time format when logging commenced on the current page. This is more accurate when mSQL-based logging is used since a timestamp is kept in each log file. For dbm-logging the time returned is the time the user's log directory was created.

getToday()

getToday returns the total number of hits the current page has had since 12 midnight local time.
This function is only available if PHP was compiled with Access Logging enabled.

getTotal()

getTotal returns the total number of hits the current page has had since access logging was started on the page.
This function is only available if PHP was compiled with Access Logging enabled.

GetType(variable)

GetType returns the type of the variable. The return value is a string and it is one of, "integer", "double" or "string". See also the SetType() function

gmDate(format,time)

gmDate is identical to the Date function except for the fact that it uses Greenwich Mean Time instead of the current local time.

Header(header_string)

The Header command is used at the top of an HTML file to send raw HTTP header strings. See the HTTP Specification for more information on raw http headers. Remember that the Header() command must be used before any actual output is sent either by normal HTML tags or by PHP echo commands.
Usage examples can be found in the HTTP Authentication section.

HexDec(hex_string)

HexDec converts a hexadecimal string to a decimal number. See also the DecHex() function.

HtmlSpecialChars(string)

HtmlSpecialChars converts any characters with ascii codes in the string argument between 160 and 255 inclusive to their corresponding HTML Entity names. The function returns the converted string. The <, >, & and " are also converted.

ImageArc(im, cx, cy, w, h, s, e, col)

ImageArc draws a partial ellipse centered at cx,cy (top left is 0,0) in the image represented by im. w and h specifies the ellipse's width and height respectively while the start and end points are specified in degrees indicated by the s and e arguments.
This function is only available if GD support has been enabled in PHP.

ImageChar(im, size, x, y, c, col)

ImageChar draws the character c in the image identified by im at coordinates x,y (top left is 0,0) in colour col. The size argument can be 1, 2, 3, 4 or 5 indicating the size of the font to be used. 1 is the smallest and 5 is the largest.
This function is only available if GD support has been enabled in PHP.

ImageCharUp(im, size, x, y, c, col)

ImageCharUp draws the character c vertically in the image identified by im at coordinates x,y (top left is 0,0) in colour col. The size argument can be 1, 2, 3, 4 or 5 indicating the size of the font to be used. 1 is the smallest and 5 is the largest.
This function is only available if GD support has been enabled in PHP.

col = ImageColorAllocate(im, red, green, blue)

ImageColorAllocate returns a colour identifier representing the colour composed of the given RGB components. The im argument is the return from the ImageCreate function. ImageColorAllocate must be called to create each colour that is to be used in the image represented by im.
This function is only available if GD support has been enabled in PHP.

ImageColorTransparent(im, col)

ImageColorTransparent sets the transparent colour in the im image to col. im is the image identifier returned by ImageCreate and col is the colour identifier returned by ImageColorAllocate. This function is only available if GD support has been enabled in PHP.

ImageCopyResized(dst_im, src_im, dstX, dstY, srcX, srcY, dstW, dstH, srcW, srcH )

ImageCopyResized copies a rectangular portion of one image to another image. dst_im is the destination image, src_im is the source image identifier. If the source and destination coordinates and width and heights differ, appropriate stretching or shrinking of the image fragment will be performed. The coordinates refer to the upper left corner. This function can be used to copy regions within the same image (if dst_im is the same as src_im) but if the regions overlap the results will be unpredictable.
This function is only available if GD support has been enabled in PHP.

im = ImageCreate(x_size, y_size)

ImageCreate returns an image identifier representing a blank image of size x_size by y_size.
This function is only available if GD support has been enabled in PHP.

im = ImageCreateFromGif(filename)

ImageCreateFromGif returns an image identifier representing the image obtained from the given filename.
This function is only available if GD support has been enabled in PHP.

ImageDestroy(im)

ImageDestroy frees any memory associated with image im. im is the image identifier returned by the ImageCreate function. This function is only available if GD support has been enabled in PHP.

ImageFill(im, x, y, col)

ImageFill performs a flood fill starting at coordinate x,y (top left is 0,0) with colour col in image im.
This function is only available if GD support has been enabled in PHP.

ImageFilledPolygon(im, points, num_points,