Wednesday, August 20, 2008

PHP Source Code for Manually Registering Global Variables

Methodology and Implementation


If you read up on the originial USENET thread, you know that there were a few suggestions made about going about this as well as posts pointing out why those solutions didn't quite fit. In order to get around some of the fallbacks and keep the original idea in tact, functions needed to be created.

By making use of PHP's superglobal arrays ($GLOBALS, $_SESSION, $_GET, $_POST, $_COOKIE, $_REQUEST, $_SERVER, $_FILES, $_ENV) and referencing variables, the solution became rather simple to accommodate the OP's idea.

You can read the thread to find out what brough on this interest if you are curious. What it comes down to is that the OP didn't want to trust register_globals, gpc_order and variables_order server settings to get it right. Therefore, the OP wanted a way to manually register the variables needed by pulling them from the appropriate place. This was to help the OP in creating more secure and stable PHP applications.

How this works is really quite simple. Say you have a variable named "var1" in a session. This variable would normally be accessed by $_SESSION['var1'] if register_globals is not turned on. That syntax creates a few extra keystrokes as well as more extra strokes when using heredoc syntax or quoted string output. However, if you were to be able to simply access that variable through $var1, that saves a lot of keystrokes when you start to use the variable over and over (as is likely the case with sessions and user input variables). For this to work correctly, however, if you were to set a value to the variable either through $var1 or $_SESSION['var1'], the compliment also needed to be changed. This is where variable references come in. (References are similar to pointers in the C programming language.)

The implementation is bery easy to use. In order to "register" or global $var1 variable, we'd simply call the correct function from below.

global_session('var1');

In doing so, we now are able to access the same value in memory by the following 3 methods:

  • $var1
  • $_SESSION['var1']
  • $GLOBALS['var1']

By setting a new value to any one of the above 3 variables will change the value for all of them.

Difference From register_globals = On

One difference I have spotted in the way these functions act from having register_globals enabled is in the case of session variables. If you had altered $var1 in a script (with PHP's register_globals = "On"), you'd have to manually add the new value back into the session. In most cases, these functions would make a more convenient method; however, there may be instances where you do not want to have the $_SESSION variable automatically updated.

Additional tests with other superglobal arrays reveal that the same behavior exists as above for all the superglobal arrays except $GLOBALS. Therefore, if you truly want to set global variable values globally, you would need to use the methods described on this page.

function global_get($var){
if(!
array_key_exists($var,$_GET))
$_GET[$var]='';
$GLOBALS[$var]=&$_GET[$var];
}

function
global_post($var){
if(!
array_key_exists($var,$_POST))
$_POST[$var]='';
$GLOBALS[$var]=&$_POST[$var];
}

function
global_session($var){
if(!
array_key_exists($var,$_SESSION))
$_SESSION[$var]='';
$GLOBALS[$var]=&$_SESSION[$var];
}

function
global_cookie($var){
if(!
array_key_exists($var,$_COOKIE))
$_COOKIE[$var]='';
$GLOBALS[$var]=&$_COOKIE[$var];
}

function
global_server($var){
if(!
array_key_exists($var,$_SERVER))
$_SERVER[$var]='';
$GLOBALS[$var]=&$_SERVER[$var];
}

function
global_files($var){
if(!
array_key_exists($var,$_FILES))
$_FILES[$var]='';
$GLOBALS[$var]=&$_FILES[$var];
}

function
global_env($var){
if(!
array_key_exists($var,$_ENV))
$_ENV[$var]='';
$GLOBALS[$var]=&$_ENV[$var];
}

function
global_request($var){
if(!
array_key_exists($var,$_REQUEST))
$_REQUEST[$var]='';
$GLOBALS[$var]=&$_REQUEST[$var];
}
?>

Creating a chat script with PHP and Ajax

Introduction

In this multi-part tutorial series I will show you how to create your own chat script with PHP and Ajax. You've probably heard of Ajax before, and what it exactly is, but in case you haven't, read the following two tutorials to learn more about Ajax: "Mastering Ajax, Part 1: Introduction to Ajax" and "Getting started with Ajax".


Another JavaScript library we'll be using is the Prototype library, which includes many useful JavaScript functions and comes with inbuilt Ajax support. If you want to know more about this library, have a look at the following tutorial: "Using prototype.js v1.3.1".


In this first part of the series I will show you how to create a really basic chat script, and nothing more. In the next parts we'll be adding more features, eventually creating a really robust and powerful chat script.


How it works


Our chat script will consist of two parts: a server and a client.


The client is used by your visitors, and doesn't contain any PHP at all. The client must do all the data sending. Every time the user wants to send a new message, the client must send this data (using Ajax) to the server. The client must also check for new messages on the server, again using an Ajax request.


The server only has to add a new message or send a list of messages to the client, and it doesn't have to use any HTML or JavaScript at all. It's strictly PHP. I've added a simple diagram below to show what I've just







Creating the server


Let's start by creating the server, but first, create a new datebase to hold the messages of your chat script, with the following database scheme:



CREATE TABLE `message` (

`messageid` int(5) NOT NULL AUTO_INCREMENT,

`user` varchar(255) NOT NULL DEFAULT '',

`message` text NOT NULL,

`datetimestamp` int(11) NOT NULL DEFAULT '0',

PRIMARY KEY (`messageid`)

) TYPE=MyISAM AUTO_INCREMENT=1 ;



The first thing the server must do is check what the client wants: adding a new message or requesting latest messages? The following code does what we want:



if (!isset($_GET['action'])) {

die('This chat server can only be used by the chat client.');

}

$action = $_GET['action'];

if ($action != 'get' AND $action != 'add') { $action = 'get'; }


// Do we want to get chat messages or add a new message?

if ($action == 'get') {

// Get messages

send_messages();

} else {

// Add a new message

add_message();

}



As you can see we're going to use two different functions: send_messages() to return all the latest messages and add_message() to add a new message.


Adding a new message is quite simple, and it only requires some standard database code, like this:


function add_message() {

global $db;

// Everything there?

if (!isset($_GET['user'])) {

die('error:no-user');

}



if (!isset($_GET['message'])) {

die('error:no-message');

}


$user = ss(htmlentities(strip_tags($_GET['user'])));

$message = ss(htmlentities(strip_tags($_GET['message'])));

$datetimestamp = time();


// Insert message

$db->query ("INSERT INTO message (user, message, datetimestamp) VALUES ('$user', '$message', $datetimestamp)");


// Return any new message

send_messages();

}



The function first checks if both variables are there, and if they're not, it returns an error. The errors look a bit weird, but this format actually makes it easier for our client (you'll see why later). When everything is okay, the message is inserted into the database.


The send_messages() function has to send the messages that have NOT yet been received by the client. To do this, the client sends the timestamp of the last received message, from which the server can automatically select the messages that haven't been received yet, like so:


function send_messages() {

global $db;

// Is there a latest timestamp?

if (!isset($_GET['latest'])) {

$latest = false;

} else {

$latest = intval($_GET['latest']);

}


// If there isn't a latest, get the five newest messages, and return them

if ($latest == false) {

$messages = $db->sql_query ("SELECT user, message, datetimestamp FROM message ORDER BY datetimestamp DESC LIMIT 0,4");

} else {

$messages = $db->sql_query ("SELECT user, message, datetimestamp FROM message WHERE datetimestamp > $latest ORDER BY datetimestamp DESC LIMIT 0,9");

}


// Any messages?

if ($messages == false) {

die('no-messages');

}


// Get newest timestamp

$newest = $messages['0']['datetimestamp'];


// Reverse array for correct order

$messages = array_reverse($messages);


// Return response

$response = $newest;


foreach ($messages as $message) {

$response .= $message['user'] . '>' . $message['message'] . "\n";

}


$response = trim($response);


die($response);

}



This code first selects the right messages, and after that returns it in the right format (each message is separated by a newline, and the user and message are separated by >).


Creating the client




You can close your PHP editor now, and switch to your HTML/JS editor, as we'll only be using HTML and JavaScript from now on.


First of all, the client page itself. It's nothing advanced, and very simple:


<html>

<head>

<title>Ajax Chat Client</title>

<script type="text/javascript" src="../prototype.js"></script>

<script type="text/javascript" src="script.js"></script>


<link REL="stylesheet" HREF="../style.css" TYPE="text/css" media="all">


</head>


<body><div id="container">

<h1>Ajax Chat Client</h1>


<div id="login">

<p>Please enter an username: </p>

<input type="text" name="user" id="user" />

<input type="button" onclick="login();" value="Enter Chatroom" />

</div>


<div id="chatelements" style="display:none;">

<textarea id="chat" rows="20"></textarea>

<input type="text" id="message"><input type="button" onclick="send_message();" value="Send" />

</div>



<div id="debug">

</div>


<div id="copyright">

This is a demo of an article series on <a href="http://www.phpit.net">PHPit</a>.

Copyright &copy; 2006 Dennis Pallett.

</div>

</div></body>

</html>



It has three important elements: the login div, which shows a login box when first viewing the page, a textarea, which is used to show all the chat messages, and a text field which is used to enter new messages.


If you have a close look at the HTML above, you'll notice two different JS functions: login() and send_message(). These are defined in the script.js file, and are the most important of our chat script.


The login() function is used to set a user's username, and getting the initial messages. It looks like this:


var server = 'http://projects/phpit/content/creating%20an%20ajax-based%20chat/demos/1/chatserver.php';

var username = '';

var latest = '';

function login() {

// Get username

var user = $F('user');


if (user == '') {

alert('Please enter a username before entering the chat room');

return false;

}


username = user;


// Show chat

Element.hide('login');

Element.show('chatelements');


$('chat').value = '';

$('message').value = '';


// Begin getting messages

get_messages();

checker = new PeriodicalExecuter(get_messages, 2);

}



The first part of the function checks the username. If everything is okay, the chat elements are shown, and the latest messages are retrieved using the get_messages() function. The function also creates a new object, called the PeriodicalExecuter, which is used to check for new messages every 2 seconds.


The get_messages() function is used to retrieve new functions using an Ajax request, like so:


function get_messages() {

var args = 'action=get&latest=' + latest;

var do_ajax = new Ajax.Request(server, {method: 'get', parameters: args, onComplete: handle_response});

}

The above code uses the Ajax object (included with the Prototype library) to send a new GET request to the server with two arguments: action and the timestamp of the latest message received. As you can see, the onComplete parameter has been set to handle_response, which means that when the Ajax request is done, the response will be sent to a function called handle_response().


The handle_response() function actually checks the response, and decides what to do. Remember the responses that we gave in the server? We're going to use that now, like so:


function handle_response(request) {

var response = request.responseText;

// Error?

if (response == 'error:no-user') {

// No username, show login again

alert('It appears you aren\'t logged in any longer. Please login again');

Element.show('login');

Element.hide('chatelements');

return false;

}

if (response == 'error:no-message') {

// No username, show login again

alert('You didn\'t send any message. Please try again');

return false;

}

if (response == 'no-messages'){

// There are no new messages

return false;

}


// We're getting a valid response, first get the latest timestamp

latest = response.substring(0, 10);


// Now get the messages

messages = response.substring(10, response.length);


// Split messages

messages = messages.split('\n');


// Add each message

var chat = $('chat');

for (var i=0; i < messages.length; i++) {

var message = messages[i].split(">");



chat.value = chat.value + '\n';

chat.value = chat.value + message[0] + ': ' + message[1];

}

}



This function first checks whether any errors have been returned. This only happens when a message has been sent (and not when receiving messages). After that it checks whether there are any messages.


If there are new messages, it parses the new messages (using some standard string functions), and then adds the new messages to the chat area.


And that's all there is to it. We've now got an almost working chat script. All that's left is to write the send_message() function.





PHP & Security: 3 Example Exploits

Introduction

One of the most common aspects of programming and scripting is security. Every program or script has to think about security, and each language has certain weak points. Actually, it isn't the language that has weak points - it's the programmer who creates weak points. PHP is no exception to this, and security should be at the top when you're creating a new script, no matter how simple or small the script may be.

I'm sure you've all read many basic PHP security articles, which include things like filtering user input, beware of XSS attacks, etc. That's why I'm not going to discuss them in this article. If you haven't heard about these things, have a look on Google. Heck, maybe I'll do a basic PHP security article in the near future.

In this article we're going to look a three different security cases. In each case I will try to explain the exploit, provide a working example, and then suggest possible fixes to prevent you from making the same mistake. Let's get cracking, shall we?

Security Case #1 - E-mail Injection

This is one of the neatest PHP exploits I've ever seen, and really requires some knowledge of how e-mail works. This exploit is often used by spammers to use contact forms on your websites to send out massive amounts of spam, without you even knowing. I used to be a victim of this as well, because I didn't even have a clue this existed. There was one thing I noticed though: really weird messages coming through my contact forms, for example:

Example

aciov@yourdomain.com
Content-Type: multipart/mixed; boundary=\"===============2145621685==\"
MIME-Version: 1.0
Subject: 9afb7555
To: aciov@yourdomain.com
bcc: mhkoch321@aol.com
From: aciov@yourdomain.com

This is a multi-part message in MIME format.

--===============2145621685==
Content-Type: text/plain; charset=\"us-ascii\"
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit

wpbtizuum
--===============2145621685==--


As you can see this doesn't make much sense at all. But what it does mean is that spammers are trying to see if your contact form is open to e-mail injection.

This exploit works quite like SQL injection - untrusted users are able to inject data, because of poor input validation. When you use the mail() function you might think each argument is a separate thing, and they can't influence each other. But that's not the case, and the e-mail is actually one big long text message. For example, mail('me@example.com', 'My Subject', 'My Message', "From: contact@example.com\r\n";) is actually changed into:

To: me@example.com
Subject: My Subject
From: contact@example.com

My Message

The exploit happens when spammers are able to insert data into the e-mail, therefore being able to change the complete e-mail. For example, if your mail() function looks like this:


$email = $_POST['email'];
mail ('me@example.com', 'My Subject', 'My Message', "From: $email\\r\\n");
?>

As you can see an attacker can inject raw data into the e-mail. This means it's now possible to send a complete different e-mail with a new subject, message, and to header. Your contact form is used as an open relay!

How do you protect against this exploit?
Easy - validate ALL input, and insert as little as possible into the e-mail. If you make sure you only get valid data from the user, the chance of e-mail injection has already been reduced hugely, and it probably won't be possibly any longer. Also see the above link for different solutions.

This is one of the sneakiest exploits around, but it is also very simple (and easy to forget about it as a developer!). The View Source exploit was the one that caused APNIPHP to be "hacked" recently.


It only works when you use a script to highlight or show the source of other PHP files, using the highlight_file() function or the fopen() function. These functions allow your visitors to view the source of other files, which is the whole point of this script. But you must also implement some security measures to prevent users from viewing files that they shouldn't see (such as database files, password files, etc). The best way of doing this is using a white-list array of filenames, and only allowing these files to be opened. This method is bullet-proof and will never fail.

But perhaps you want to restrict the script to only allow files from a certain directory, e.g. the 'demos' directory. To enforce this restriction, you'd probably use code like this:

if (strpos($file, 'demos') === false) {
echo 'Security alert. Not a demo!';
} else {
highlight_file ($file);
}

This checks whether the filename contains 'demos', and if so, displays the source. Seems fairly fail-proof, but that's where the exploit strikes. An attacker could include '..' in the filename, which means "go a directory up". So C:\program files\demos\..\ means the same as C:\program files\. This basically means that an attacker has unlimited access to everything on the server. Big whoops!

How do you protect against this exploit?
The easiest way is to check if the filename contains the two dots and display an error. So the above code becomes:

if (strpos($file, 'demos') === false OR strpos($file, '..') !== false) {
echo 'Security alert. Not a demo!';
} else {
highlight_file ($file);
}

UPDATE:
The above way isn't completely secury, and any file that contains 'demos' in the filename can still be viewed. If you really want to secure your view source script, don't allow a full path, and instead only allow a name. For example, instead of using '/home/phpit/public_html/demo/demo.php' simply use 'demo.php', and in your script add the full path. The only thing you have to worry about then is to filter out the two dots, and that's easy.

$file = '/home/phpit/public_html/demo/' . $_GET['filename'];

if (strpos($file, '..') !== false) {
echo 'Security alert. Not a demo!';
} else {
highlight_file ($file);
}

This would probably be enough to protect your view source script, and stop this exploit from working. You can also use dedicated source-viewing scripts, like phpViewSource.

How do you protect against this exploit?
Protecting your scripts against CSRF attacks is extremely hard to do, and a really dedicated attacker will likely succeed anyway. But there are still steps you can take to make it harder.

First of all, make sure that any forms that change data (add/edit/delete) are POST only. GET requests should not be able to change anything.

Secondly, include a secret token with your forms, which also expire after a certain period of time. This will prevent almost any kind of CSRF attack, and is extremely different to counter.

Finally, don't worry too much about CSRF attacks. Although they are out there, it's likely you won't ever have to deal with it, and even so, it's an easy fix. If you're interested have a look on http://www.squarefree.com/securitytips/web-developers.html#CSRF for more information about CSRF attacks.


PHP Global Variables

Introduction

Whenever you're developing a new large-scale PHP script, you're bound to use global variables, since some data needs to be used by multiple parts of your script. Good examples of global data are script settings, database connections, user credentials and more. There are many ways of making this data global, but the most commonly used way is to use the global keyword, which we will explore later on in this article.

The only problem with the global keyword, and any global data for that matter, is that's it's actually a very bad way of programming, and usually tends to lead to bigger problems later on. The reason for this is that global data ties all the separate parts of your script together, and often if you make a change in one part, something else will break in another part. If you have more than a few global variables, you're whole script will eventually become a big kludge of unmaintainable code.

That's why this article will show you how to prevent this by using various techniques and design patterns. But first, let's have a look at the global keyword and how it works.

Using globals and the global keyword

By default PHP defines a few variables called Superglobals which are automatically global, and can be accessed anywhere, like the $_GET or $_REQUEST variables. These are mainly used to retrieve form data or other outside data, and there's no real harm in using these variables, since they should never be written to anyway. But you can also use your own global variables, with the global keyword which is used to import variables from the global scope into the local scope of a function.

The following example demonstrates use of the global keyword:

$my_var = 'Hello World';

test_global();

function test_global() {
// Now in local scope
// the $my_var variable doesn't exist

// Produces error: "Undefined variable: my_var"
echo $my_var;

// Now let's important the variable
global $my_var;

// Works:
echo $my_var;
}

?>


As you can see in the above example, the global keyword is used to important variables from the global scope. Seems to work fine, and it's nice and simple, so why should you worry about using the global keyword?

There are three good reasons:

1. Reusing parts of the script is impossible
If a certain function relies on global variables, it becomes almost impossible to use that function in a different context. Another problem is that you can't take that function, and use it in another script.

2. Solving bugs is much harder
Tracking a global variable is much harder than a non-global variable. A global variable could be declared in some obscure include file, which could take hours to find, although a good text editor / IDE could help with this.

3. Understanding the code in a year will be much more difficult
Globals make it difficult to see where a variable is coming from and what it does. You might know about every global during development, but after a year or so you'll probably have forgotten at least half of them, and then you'll be kicking yourself for using so many globals.

Google tips and tricks- Google don'ts

Google tips:

Bellow are some techniques which may reduce your Google ranking or even ban you from its index. You should avoid them if possible.

Bad navigation

Your website must have clean and simple navigation. This way you ensure that Googlebot will be able to crawl your entire site. Navigation links should be located near the top of the pages since this makes it easy for your visitors and Googlebot to navigate through your site.
Best bet for navigation is use of text links, as this increases word count and keyword density, as well as giving description of destination page to Googlebot. Googlebot is also able to follow image links and from recently Flash navigation links. If you use image links make sure you add some description in “alt” attribute of image tag to describe your link.

JavaScript links

Googlebot is not able (currently) to follow JavaScript links. People often use these type of links for fancy navigation. If you use them just make sure you have alternative navigation using HTML links.

Hidden text

Googlebot and other robots learned to recognize this method several years ago. So if you don’t want to be identified as spammer and banned from SERP’s, don’t use this method.

Hidden links

Number of incoming links to certain page has direct effect to Google PageRank (PR). However, if those are hidden that may produce similar results as with hidden text.

Cloaking

Cloaking is a search engine optimization method where you serve highly optimized page version to robots and a regular page to your visitors. Official Google policy is that cloaked pages will not be allowed in their index. However, there are many websites that use cloaking with great success. So if you like to risk getting banned from SERP’s you may use this method, just make sure you do it properlyJ

Guest book spamming and FFA pages

Adding your link to hundreds of guest books will not help you with your PR, since it appears that Google is able to detect them and ignores outgoing links completely. This way you’ll save yourself many hours of useless work.
When PR was initially introduced, many SEO companies were offering to “submit your site to zillion FFA pages for free” and hopefully increase your PR. I don’t remember that this used to work at time and it certainly doesn’t work now. If you find any of these, avoid them.

Sessions

Google is not able to accept session cookies and will try avoiding URL based sessions. Also, you should use fewer parameters in you dynamic URLs and avoid use “id” parameter as Googlebot may think that is session ID.

Simple Mini Poll class library

This easy-to-use class library enables you to set up your own survey system in just few minutes.

Main features include:
  • Dynamically generated form (with number of total votes)
  • Detailed result page
  • View of old polls
  • Poll administration interface
  • Check for repeated votes
1 . Execute these queries on your database:

# Table structure for table `poll_check`

CREATE TABLE `poll_check` (
`
pollid` int(11) NOT NULL default '0',
`
ip` varchar(20) NOT NULL default '',
`
time` varchar(14) NOT NULL default ''
) TYPE=MyISAM COMMENT='';

# -----------------------------------------

# Table structure for table `poll_data`

CREATE TABLE `poll_data` (
`
pollid` int(11) NOT NULL default '0',
`
polltext` varchar(50) NOT NULL default '',
`
votecount` int(11) NOT NULL default '0',
`
voteid` int(11) NOT NULL default '0',
`
status` varchar(6) default NULL
) TYPE=MyISAM COMMENT='';

# -----------------------------------------

# Table structure for table `poll_desc`

CREATE TABLE `poll_desc` (
`
pollid` int(11) NOT NULL default '0',
`
polltitle` varchar(100) NOT NULL default '',
`
timestamp` datetime NOT NULL default '0000-00-00 00:00:00',
`
votecount` mediumint(9) NOT NULL default '0',
`
STATUS` varchar(6) default NULL,
PRIMARY KEY (`pollid`)
)
TYPE=MyISAM COMMENT='';

# -----------------------------------------
?>

2. Set up database connection parameters.

3. Paste this code on page where you wish poll to appear:


include_once ("includes/miniPoll.class.php");

$test = new miniPoll;

$test->pollForm();

?>

4. Paste this code on page where you wish poll results to appear:


include_once ("includes/miniPoll.class.php");

$test = new miniPoll;

if (isset(
$_GET['poll']) && is_numeric($_GET['pollid'])) {
$pollid = $_GET['pollid'];

if (isset(
$_GET['voteid']) && is_numeric($_GET['voteid'])) {
$voteid = $_GET['voteid'];
$test->processPoll($pollid, $voteid);
}

}
if (isset(
$_GET['pollid'])) {
$pollid = $_GET['pollid'];
$test->pollResults($pollid);
}

?>

5. Paste this code on poll admin page:


include_once ("includes/miniPollAdmin.class.php");

$test = new miniPollAdmin;

$test->newPollForm();

if (isset(
$_GET['opt'])) {
$opt = $_GET['opt'];
$pollid = $_GET['pollid'];
if (
$opt == 'activate') {
$test->activatePoll($pollid);
}
if (
$opt == 'delete') {
$test->deletePoll($pollid);
}

}

echo
"
"
;
if (isset(
$_GET['q'])) {
$pollname = $_GET['pollname'];
$q = $_GET['q'];
$test->createPoll($pollname, $q);
}
$test->listPolls();

?>


6. Set up these parameters in miniPoll.class.php:

->results_page = "test_poll_results.php"; ?>
page where you display results

7. Set up these parameters in miniPollAdmin.class.php:

->results_page = "test_poll_admin.php"; ?>
name of admin page file

8. Optionally you can change layout of form and results page
9. Create new poll by starting admin page
10. Activate your poll by clicking ACTIVATE
11. Enjoy and send me your comments

How to create and use Favicon.ico file

What is Favicon.ico?


Favicon is a small icon which appears next to your URL in browser address bar.


Why would I use it?


If you look around the Internet, you will notice that all professional web sites use it. It gives more customized appearance of your site in visitor browser and it also gives more distinct look of your site in Bookmarks menu by replacing generic browser icon.


What browsers support it?


Currently all modern browsers support it. Including: Internet Explorer, Mozilla Firefox, Opera, Netscape 7.0 and Mozilla.


How do I create Favicon?


Best solution would be to get some of popular icon editors. If you don't have icon editor, you may use some of the standard image editors like Photoshop, PaintShop or even Windows paint. Simply create 16x16 pixels bitmap image with standard 16 or 256 Windows icon colors. You can't put much in such a small space, but with wright color combinations you may achieve very effective solutions. When you're done editing, simply rename file to favicon.ico.


Where do I put Favicon.ico file?


Simply use your favorite FTP program and upload it in root folder of your web site. Most browser look there for it. You may also help them by inserting following code in section of your page:


<link href="favicon.ico" rel="SHORTCUT ICON">


This way you ensure that browser will find it. You may also put favicon file in different folder, like for example, in your images folder. In that case code may look like this:


<link href="images/favicon.ico" rel="SHORTCUT ICON">

User Online Class

Description:

This very simple class enables you to track number of visitors online in an easy and accurate manner.

Main features include:
  • Automatic insertion of new user
  • Automatic database cleanup
  • Check if user is coming behind proxy server (this helps in script accuracy)
  • Display of users online
  • Error reporting

DATABASE STRUCTURE
CREATE TABLE
`useronline` (
`
id` int(10) NOT NULL auto_increment,
`
ip` varchar(15) NOT NULL default '',
`
timestamp` varchar(15) NOT NULL default '',
PRIMARY KEY (`id`),
UNIQUE KEY `id`(`id`)
)
TYPE=MyISAM COMMENT='' AUTO_INCREMENT=1 ;
?>



PHP CODE :
include_once ("usersOnline.class.php");
$visitors_online = new usersOnline();

if (
count($visitors_online->error) == 0) {

if (
$visitors_online->count_users() == 1) {
echo
"There is " . $visitors_online->count_users() . " visitor online";
}
else {
echo
"There are " . $visitors_online->count_users() . " visitors online";
}
}
else {
echo
"Users online class errors:
    \r\n";
    for (
    $i = 0; $i < count($visitors_online->error); $i ++ ) {
    echo
    "
  • " . $visitors_online->error[$i] . "
  • \r\n"
    ;
    }
    echo
    "
\r\n"
;

}
?>

Tuesday, August 12, 2008

PHP Array

An array is a data structure that stores one or more values in a single value. For experienced programmers it is important to note that PHP's arrays are actually maps (each key is mapped to a value).

PHP - A Numerically Indexed Array

If this is your first time seeing an array, then you may not quite understand the concept of an array. Imagine that you own a business and you want to store the names of all your employees in a PHP variable. How would you go about this?

It wouldn't make much sense to have to store each name in its own variable. Instead, it would be nice to store all the employee names inside of a single variable. This can be done, and we show you how below.
PHP Code:

$employee_array[0] = "Bob";
$employee_array[1] = "Sally";
$employee_array[2] = "Charlie";
$employee_array[3] = "Clare";

In the above example we made use of the key / value structure of an array. The keys were the numbers we specified in the array and the values were the names of the employees. Each key of an array represents a value that we can manipulate and reference. The general form for setting the key of an array equal to a value is:

* $array[key] = value;

If we wanted to reference the values that we stored into our array, the following PHP code would get the job done.

Note: As you may have noticed from the above code example, an array's keys start from 0 and not 1. This is a very common problem for many new programmers who are used to counting from 1 and lead to "off by 1" errors. This is just something that will take experience before you are fully comfortable with it.
PHP Code:

echo "Two of my employees are "
. $employee_array[0] . " & " . $employee_array[1];
echo "
Two more employees of mine are "

. $employee_array[2] . " & " . $employee_array[3];

Display:
Two of my employees are Bob & Sally
Two more employees of mine are Charlie & Clare

PHP arrays are quite useful when used in conjunction with loops, which we will talk about in a later lesson. Above we showed an example of an array that made use of integers for the keys (a numerically indexed array). However, you can also specify a string as the key, which is referred to as an associative array.
PHP - Associative Arrays

In an associative array a key is associated with a value. If you wanted to store the salaries of your employees in an array, a numerically indexed array would not be the best choice. Instead, we could use the employees names as the keys in our associative array, and the value would be their respective salary.
PHP Code:

$salaries["Bob"] = 2000;
$salaries["Sally"] = 4000;
$salaries["Charlie"] = 600;
$salaries["Clare"] = 0;

echo "Bob is being paid - $" . $salaries["Bob"] . "
";

echo "Sally is being paid - $" . $salaries["Sally"] . "
";

echo "Charlie is being paid - $" . $salaries["Charlie"] . "
";

echo "Clare is being paid - $" . $salaries["Clare"];

Display:
Bob is being paid - $2000
Sally is being paid - $4000
Charlie is being paid - $600
Clare is being paid - $0

Once again, the usefulness of arrays will become more apparent once you have knowledge of for and while loops.

PHP Require

Just like the previous lesson, the require command is used to include a file into your PHP code. However there is one huge difference between the two commands, though it might not seem that big of a deal.


Require vs Include

When you include a file with the include command and PHP cannot find it you will see an error message like the following:
PHP Code:



Display:
Warning: main(noFileExistsHere.php): failed to open stream: No such file or directory in /home/websiteName/FolderName/tizagScript.php on line 2 Warning: main(): Failed opening 'noFileExistsHere.php' for inclusion (include_path='.:/usr/lib/php:/usr/local/lib/php') in /home/websiteName/FolderName/tizagScript.php on line 2

Hello World!

Notice that our echo statement is still executed, this is because a Warning does not prevent our PHP script from running. On the other hand, if we did the same example but used the require statement we would get something like the following example.
PHP Code:



Display:
Warning: main(noFileExistsHere.php): failed to open stream: No such file or directory in /home/websiteName/FolderName/tizagScript.php on line 2
Fatal error: main(): Failed opening required 'noFileExistsHere.php' (include_path='.:/usr/lib/php:/usr/local/lib/php') in /home/websiteName/FolderName/tizagScript.php on line 2

The echo statement was not executed because our script execution died after the require command returned a fatal error! We recommend that you use require instead of include because your scripts should not be executing if necessary files are missing or misnamed.

PHP Include

Without understanding much about the details of PHP, you can save yourself a great deal of time with the use of the PHP include command. include takes a file name and simply inserts that file's contents into the script that issued the include command.

Why is this a cool thing? Well, first of all, this means that you can type up a common header or menu file that you want all your web pages to include. When you add a new page to your site, instead of having to update the links on several web pages, you can simply change the Menu file.


An Include Example

Say we wanted to create a common menu file that all our pages will use. A common practice for naming files that are to be included is to use the ".php" extension. Since we want to create a common menu let's save it as "menu.php".

menu.php Code:
< html>
< body>
Home -
About Us -
Links -
Contact Us


Save the above file as "menu.php". Now create a new file, "index.php" in the same directory as "menu.php". Here we will take advantage of the include command to add our common menu.
index.php Code:


This is my home page that uses a common menu to save me time when I add
new pages to my website!


< /body>
< /html>

And we would do the same thing for "about.php", "links.php", and "contact.php". Just think how terrible it would be if you had 15 or more pages with a common menu and you decided to add another web page to that site. You would have to go in and manually edit every single file to add this new page, but with include files you simply have to change "menu.php" and all your problems are solved. Avoid such troublesome occasions with a simple include file.
What do Visitors See?

If we were to use the include command to insert a menu on each of our web pages, what would the visitor see if they viewed the source of "index.php"? Well, because the include command is pretty much the same as copying and pasting, the visitors would see:
View Source of index.php to a Visitor:

< html>
< body>
Home -
About Us -
Links -
Contact Us

This is my home page that uses a common menu to save me time when I add
new pages to my website!


< /body>
< /html>

The visitor would actually see all the HTML code as one long line of HTML code, because we have not inserted any new line characters. We did some formatting above to make it easier to read. We will be discussing new line characters later.

Passing JavaScript variables to PHP

JavaScript is mainly used as a client side scripting language, while PHP is a server side technology. Unlike Java or ASP.Net, PHP doesn't have tools to make it work client side. That is why you need to combine JavaScript and PHP scripts to develop powerful web-applications.

One of the frequent problems is defining visitor’s screen resolution using JavaScript tools and passing this data to PHP-script. The following script provides solution for this problem:



Copy and paste this code snippet in the text editor, save it as index.htm and run it in your browser. After this code has been executed, a user is automatically redirected to the main.php page where screen resolution is displayed in the browser window.

The main.php looks as follows:


echo "

Screen Resolution:

";

echo "Width : ".$_GET['width']."
";

echo "Height : ".$_GET['height']."
";

?>

How to Get the Current Page URL in PHP

Sometimes, you might want to get the current page URL that is shown in the browser URL window. For example if you want to let your visitors submit a blog post to Digg you need to get that same exact URL. There are plenty of other reasons as well. Here is how you can do that.

Add the following code to a page:

function curPageURL() {
$pageURL = 'http';
if ($_SERVER["HTTPS"] == "on") {$pageURL .= "s";}
$pageURL .= "://";
if ($_SERVER["SERVER_PORT"] != "80") {
$pageURL .= $_SERVER["SERVER_NAME"].":".$_SERVER["SERVER_PORT"].$_SERVER["REQUEST_URI"];
} else {
$pageURL .= $_SERVER["SERVER_NAME"].$_SERVER["REQUEST_URI"];
}
return $pageURL;
}
?>

You can now get the current page URL using the line:

echo curPageURL();
?>
Sometimes it is needed to get the page name only. The following example shows how to do it:


function curPageName() {
return substr($_SERVER["SCRIPT_NAME"],strrpos($_SERVER["SCRIPT_NAME"],"/")+1);
}

echo "The current page name is ".curPageName();
?>

PHP: Dynamic Image Generation

Creating images on the fly can be a very useful skill. PHP has some built-in image generation functions, further more, to generate new images or edit existing images on the fly using PHP, we need to have the GD library installed. In this tutorial we will show you how to get quite interesting and useful effects using image handling functions. We will review two practical tasks: creating security images (captcha) on the fly and building a bar chart using numerical values retrieved from MySQL database.


Creating security images on the fly

At first, have a look at the following script that creates captcha image. Next, we will consider each step of image generation in details.


//Send a generated image to the browser
create_image();
exit();

function create_image()
{
//Let's generate a totally random string using md5
$md5 = md5(rand(0,999));
//We don't need a 32 character long string so we trim it down to 5
$pass = substr($md5, 10, 5);

//Set the image width and height
$width = 100;
$height = 20;

//Create the image resource
$image = ImageCreate($width, $height);

//We are making three colors, white, black and gray
$white = ImageColorAllocate($image, 255, 255, 255);
$black = ImageColorAllocate($image, 0, 0, 0);
$grey = ImageColorAllocate($image, 204, 204, 204);

//Make the background black
ImageFill($image, 0, 0, $black);

//Add randomly generated string in white to the image
ImageString($image, 3, 30, 3, $pass, $white);

//Throw in some lines to make it a little bit harder for any bots to break
ImageRectangle($image,0,0,$width-1,$height-1,$grey);
imageline($image, 0, $height/2, $width, $height/2, $grey);
imageline($image, $width/2, 0, $width/2, $height, $grey);

//Tell the browser what kind of file is come in
header("Content-Type: image/jpeg");

//Output the newly created image in jpeg format
ImageJpeg($image);

//Free up resources
ImageDestroy($image);
}
?>
To create a new image or edit an existing one, we need to create image identifier. In the preceding example we created an empty canvas by calling ImageCreate() function, passing it width and height of a new image as a parameters. Another way to do it is to read the existing image from the file. Depending on the file format you can do it using one of the following functions: ImageCreateFromPNG(), ImageCreateFromGIF(), ImageCreateFromJPEG(). Parameter of each function is a file name.

Then, we need to choose colors to be used while painting. For this we can use ImageColorAllocate() function and image identifiers for red, green, and blue (RGB) components of necessary color will be passed as parameters.

On the next step, we will generate our image. First, using ImageFill() function we will create black background. Parameters of this function are: image identifier, initial coordinates of the area to be filled and fill color. Then, we will use ImageString() function to add text to the image. Its parameters are – image identifier, font, coordinates for the first text position and text color. Finally, we will draw two lines and a rectangular to protect our image a little bit. Please note, that the final point of the rectangular has the following coordinates: $width-1 and $height-1. If they were equal to $width and $height, than the rectangular would have exceeded canvas frame.

When we had created the image, we can output it either to a browser, or to a file. Our example shows how to output it to the browser. We need to inform the browser, that we will output the image, not the text or html-code. To do it, call Header() function, setting image MIME-type. It’s worth mentioning that Header() function can not be executed if HTTP header has already been sent. After sending the header we can output our image using ImageJpeg() function, passing it image identifier as a parameter.

When we have finished working with the image we need to free up resources using ImageDestroy() function.

Building a bar chart

In the example below, using graphic functions we will build a bar chart based on the values stored in MySQL database. In our case, values represent poll results.

In this example we will use poll database. To create it run the following SQL script in your MySQL server:
CREATE DATABASE `poll`;
USE poll;

CREATE TABLE `results` (
book_type VARCHAR(50),
num_votes INT
);

INSERT INTO `results` values
('Classic', 15),
('Fantasy', 7),
('Humor', 32),
('Mystery', 12),
('Poetry', 25);

Script building a bar chart is quite long, so let's divide it into two parts and discuss them separately. The first part of the script connects to MySQL database and requests data that will be represented in the bar chart.

//Querying the database to get poll results

//connection to the database
$dbhandle = mysql_connect("localhost", "root", "")
or die("Unable to connect to MySQL");

//select a database to work with
$selected = mysql_select_db("poll",$dbhandle)
or die("Could not select examples");

//execute the SQL query and return records
$result = mysql_query("SELECT * FROM results");

$num_poller = mysql_num_rows($result);
$total_votes = 0;

//fetch the data from the database
while ($row = mysql_fetch_array($result)) {
$total_votes += $row{'num_votes'}; //calculating total number of votes
}

//nulling the pointer $result
mysql_data_seek($result,0);

//close the connection
mysql_close($dbhandle);

In the second part of the script first of all we will calculate variables needed to build the chart. Then, we prepare primary image and actually output data. Results for each genre are picked from the database one by one, percentage of votes is calculated, and then bars and explanatory notes are outputted.

In this script we are using TrueType fonts to get anti-aliased text. Functions that work with the TrueType fonts have its own peculiarities. First, you need to point where the fonts are located. For this, system variable GDFONTPATH is set. Then, we need to set the font name. TrueType fonts are rendered using ImageTTFText().

We have already discussed above all functions used for drawing, the code has been commented and is quite clear, so you shouldn’t have any trouble.

//Tell gd2, where your fonts reside
putenv('GDFONTPATH=C:\WINDOWS\Fonts');
$font = 'arial';

//Set starting point for drawing
$y = 50;

//Specify constant values
$width = 700; //Image width in pixels
$bar_height = 20; //Bars height
$height = $num_poller * $bar_height * 1.5 + 70; //Calculating image height
$bar_unit = ($width - 400) / 100; //Distance on the bar chart standing for 1 unit

//Create the image resource
$image = ImageCreate($width, $height);

//We are making four colors, white, black, blue and red
$white = ImageColorAllocate($image, 255, 255, 255);
$black = ImageColorAllocate($image, 0, 0, 0);
$red = ImageColorAllocate($image, 255, 0, 0);
$blue = imagecolorallocate($image,0,0,255);

//Create image background
ImageFill($image,$width,$height,$white);
//Draw background shape
ImageRectangle($image, 0, 0, $width-1, $height-1, $black);
//Output header
ImageTTFText($image, 16, 0, $width/3 + 50, $y - 20, $black, $font, 'Poll Results');

while ($row = mysql_fetch_object($result)) {
if ($total_votes > 0)
$percent = intval(round(($row->num_votes/$total_votes)*100));
else
$percent = 0;

//Output header for a particular value
ImageTTFText($image,12,0,10, $y+($bar_height/2), $black, $font, $row->book_type);
//Output percentage for a particular value
ImageTTFText($image, 12, 0, 170, $y + ($bar_height/2),$red,$font,$percent.'%');

$bar_length = $percent * $bar_unit;

//Draw a shape that corresponds to 100%
ImageRectangle($image, $bar_length+221, $y-2, (220+(100*$bar_unit)), $y+$bar_height, $black);
//Output a bar for a particular value
ImageFilledRectangle($image,220,$y-2,220+$bar_length, $y+$bar_height, $blue);
//Output the number of votes
ImageTTFText($image, 12, 0, 250+100*$bar_unit, $y+($bar_height/2), $black, $font, $row->num_votes.' votes cast.');

//Going down to the next bar
$y = $y + ($bar_height * 1.5);

}

//Tell the browser what kind of file is come in
header("Content-Type: image/jpeg");

//Output the newly created image in jpeg format
ImageJpeg($image);

//Free up resources
ImageDestroy($image);
?>


Using dynamically generated images on the other pages


Since the header can be sent only once and it is the only way to tell the browser that you are going to send image, it is not so easy to insert automatically generated images to the regular pages. There are three ways to do it:

* The whole page can consist of the image.
* You can save image in the file and then refer to it using HTML descriptor.
* You can put a script producing image in HTML descriptor, e.g.:

Dynamically generated image