<?xml version="1.0" encoding="UTF-8" ?>

<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/">
	<channel>
			<title>Tagged with "tutorial"</title>
			<link>http://www.addedbytes.com/feeds/tag-feed/</link>
			<description></description>
			<language>en</language>
			<copyright>Added Bytes - Brighton Web Application Development 2006</copyright>
			<ttl>120</ttl>
			<item>
				<title>Writing Secure PHP, Part 4</title>
				<link>http://www.addedbytes.com/writing-secure-php/writing-secure-php-4/</link>
				<description><![CDATA[ The fourth part of the <a href="http://www.addedbytes.com/writing-secure-php/">Writing Secure PHP</a> series, covering cross-site scripting, cross-site request forgery and character encoding security issues. <p>In <a href="http://www.addedbytes.com/php/writing-secure-php/">Writing Secure PHP</a>, <a href="http://www.addedbytes.com/security/writing-secure-php-2/">Writing Secure PHP, Part 2</a> and <a href="http://www.addedbytes.com/security/writing-secure-php-3/">Writing Secure PHP, Part 3</a> I covered many of the common mistakes PHP developers make, and how to avoid some potential security problems. This article covers some of the more advanced security problems common to PHP on the web.</p>

<h3>Cross-Site Scripting (XSS)</h3>

<p>Cross-site scripting (often abbreviated to XSS) is a form of injection, where an attacker finds a way to have the target site display code they control. In its most basic form, this can be as simple as a site that allows HTML characters in usernames, where someone can specify a username like:</p>

<pre class="php">DaveChild&lt;script type="text/javascript" src="http://www.example.com/my_script.js"&gt;&lt;/script&gt;</pre>

<p>Now, whenever someone sees my username on the target site, the script I've added to my username will run. I could potentially use this to grab the person's login information, log their keystrokes - any number of nefarious activities.</p>

<p>As a developer, you can combat this type of attack by encoding or removing HTML characters (watch out for character encoding issues, as outlined next). Even better than stripping out unwanted characters is to allow a whitelist of safe characters in usernames and other fields. Be especially careful with e-commerce sites where you are listing orders in a CMS - an XSS vulnerability may allow an attacker to gain administrative access to your CMS. It is also important to turn off TRACE and TRACK support on the server, as if there is a vulnerability (and always assume that despite your best efforts there will be) these potentially allow an attacker to steal a user's cookie.</p>

<p>As a user you are also vulnerable to this sort of attack, and it is very difficult, at the moment, to make yourself safe against it. Vigilance is key, and to that end I have released a <a href="http://www.addedbytes.com/tools/xss-alarm-userscript/">userscript that warns you about third party scripts</a> (for users of GreaseMonkey, Opera or Chrome).</p>

<h3>Cross-Site Request Forgery (CSRF)</h3>

<p>Despite the similar name, CSRF is unconnected to XSS. CSRF is a form of attack where an authenticated user performs an action on a site without knowing it.</p>

<p>Let's assume that Jack is logged in to his bank, and has a cookie stored on his computer. Each time he sends an HTTP request to the bank (i.e., views a page or an image on a page) his browser sends the cookie along with the request so that the bank knows that it's him making the request.</p>

<p>Jill, meanwhile, runs a different website and has managed to get Jack to visit it. One of the items on the page is in fact loaded from the bank, for example in an iframe. The URL of the iframe or request contains instructions to the bank to transfer money from Jack's account to Jill's. Because the request is coming from Jack's computer, and includes his cookie, the bank assumes it is a legitimate request and the money is transferred.</p>

<p>This type of attack is extremely dangerous and virtually untracable. As a developer, your job is to protect against it, and the best way to do that is to remember <a href="http://www.addedbytes.com/php/writing-secure-php/">Rule Number One: Never, Ever Trust Your Users</a>. No matter how authenticated they are, do not assume every request was intended.</p>

<p>In practical PHP terms, you can combat CSRF with several relatively simple coding habits. Never let the user do anything with a GET request - always use POST. Confirm actions before performing them with a confirmation dialog on a separate page - and make sure <em>both</em> the original action button or link <em>and</em> the confirmation were clicked. Even better, have the user enter information like letters from their password on the confirmation page.</p>

<p>Add a randomly generated token to forms and verify its presence when a request is made. Use <a href="http://javascript.internet.com/page-details/break-frames.html">frame-breaking JavaScript</a>. Time-out sessions with a short timespan (think minutes, not hours). Encourage the user to log out when they've finished. Check the HTTP_REFERER header (it can be hidden, but is still worth checking as if it is a different domain to that expected it is definitely a CSRF request).</p>

<h3>Character Encoding</h3>

<p>Character encoding in PHP and associated database systems is worthy of its own series. In any one request, there may be more different character encodings in use than you might think.</p>

<p>For example, a single request and response (uploading a file to a server and writing information to a database) may involve all of the following differently items with different character encodings: the HTTP request headers, post data, PHP's default encoding, the PHP MySQL module, MySQL's default set, the set of each table being used, a file being opened and read, a new file being created and written, the response headers and the response body.</p>

<p>English-speaking developers generally don't have much cause to get embroiled in character encoding issues, and that results in a lot of developers with a serious lack of understanding of how character encodings work and fit together. For those that do have a reason to look at character encodings, usually that interest ends with the setting of the response's character set.</p>

<p>However, character sets are a fundamental part of all web development. English alone can exist in any one of a wide variety of sets, and developers are usually familiar with the most common two: ISO-8859-1 and UTF-8. Fewer are familiar with UCS-2, UTF-16 or windows-1252. Still fewer are familiar with commonly used alternative language sets (e.g, GB2312 for Chinese).</p>

<p>Which, in a very roundabout way, brings me on to the security pitfalls of character encodings. Where data is processed by PHP using one character set, but a database server uses a different character set, a character (or series of characters) deemed safe by PHP may in fact allow SQL injection against the database.</p>

<p>PHP security expert Chris Shiflett <a href="http://shiflett.org/blog/2006/jan/addslashes-versus-mysql-real-escape-string">has written about this issue</a> and included an example of how it can be exploited to allow SQL injection even where input is sanitized using addslashes().</p>

<p>The solution is to always <em>always</em> use mysql_real_escape_string() rather than addslashes() (or use prepared statements / stored procedures), and to explicitly state character sets at all stages of interaction. Ideally, use the same character set throughout your system (UTF-8 is recommended) and where PHP allows you to specify a character encoding for a function (e.g., htmlspecialchars() or htmlentities()), make use of it.</p>

<p>It's not just SQL that's vulnerable as a result of character encoding bugs. Cross-site scripting is possible even where HTML characters are escaped if character sets are not handled properly. Fortunately, once again that is simple to avoid by properly setting character encodings at all stages of the process and specifying character encoding for functions where possible.</p> <br><br>]]></description>
				<pubDate>Thu, 11 Sep 2008 12:11:14 +0000</pubDate>
				<guid isPermaLink="false">http://www.addedbytes.com/writing-secure-php/writing-secure-php-4/</guid>
				<dc:creator>Dave Child</dc:creator>
				<a href="/feeds/tag-feed/?tags=code&amp;start=0" class="ditto_tag" rel="tag">code</a>,<a href="/feeds/tag-feed/?tags=coding&amp;start=0" class="ditto_tag" rel="tag">coding</a>,<a href="/feeds/tag-feed/?tags=development&amp;start=0" class="ditto_tag" rel="tag">development</a>,<a href="/feeds/tag-feed/?tags=mysql&amp;start=0" class="ditto_tag" rel="tag">mysql</a>,<a href="/feeds/tag-feed/?tags=php&amp;start=0" class="ditto_tag" rel="tag">php</a>,<a href="/feeds/tag-feed/?tags=programming&amp;start=0" class="ditto_tag" rel="tag">programming</a>,<a href="/feeds/tag-feed/?tags=security&amp;start=0" class="ditto_tag" rel="tag">security</a>,<a href="/feeds/tag-feed/?tags=tips&amp;start=0" class="ditto_tag" rel="tag">tips</a>,<a href="/feeds/tag-feed/?tags=tutorial&amp;start=0" class="ditto_tag" rel="tag">tutorial</a>,<a href="/feeds/tag-feed/?tags=web&amp;start=0" class="ditto_tag" rel="tag">web</a>,<a href="/feeds/tag-feed/?tags=webdesign&amp;start=0" class="ditto_tag" rel="tag">webdesign</a>,<a href="/feeds/tag-feed/?tags=webdev&amp;start=0" class="ditto_tag" rel="tag">webdev</a>
			</item>

			<item>
				<title>Writing Secure PHP, Part 1</title>
				<link>http://www.addedbytes.com/writing-secure-php/writing-secure-php-1/</link>
				<description><![CDATA[ Learn how to avoid some of the most common mistakes in PHP, and so make your sites more secure. <p><a href="http://www.php.net">PHP</a> is a very easy language to learn, and many people without any sort of background in programming learn it as a way to add interactivity to their web sites. Unfortunately, that often means PHP programmers, especially those newer to web development, are unaware of the potential security risks their web applications can contain. Here are a few of the more common security problems and how to avoid them.</p>

<p>[Writing Secure PHP is a series. <a href="http://www.addedbytes.com/php/writing-secure-php-2/">Part 2</a>, <a href="http://www.addedbytes.com/php/writing-secure-php-3/">Part 3</a> and <a href="http://www.addedbytes.com/php/writing-secure-php-4/">Part 4</a> are currently also available.]</p>

<h3>Rule Number One: Never, Ever, Trust Your Users</h3>

<p>It can never be said enough times, you should never, ever, ever trust your users to send you the data you expect. I have heard many people respond to that with something like "Oh, nobody malicious would be interested in my site". Leaving aside that that could not be more wrong, it is not always a malicious user who can exploit a security hole - problems can just as easily arise because of a user unintentionally doing something wrong.</p>

<p>So the cardinal rule of all web development, and I can't stress it enough, is: <strong>Never, Ever, Trust Your Users</strong>. Assume every single piece of data your site collects from a user contains malicious code. Always. That includes data you think you have checked with client-side validation, for example using JavaScript. If you can manage that, you'll be off to a good start. If PHP security is important to you, this single point is the most important to learn. Personally, I have a "PHP Security" sheet next to my desk with major points on, and this is in large bold text, right at the top.</p>

<h3>Global Variables</h3>

<p>In many languages you must explicitly create a variable in order to use it. In PHP, there is an option, "register_globals", that you can set in php.ini that allows you to use global variables, ones you do not need to explicitly create. </p>

<p>Consider the following code:</p>

<pre class="php">if ($password == "my_password") {
    $authorized = 1;
}

if ($authorized == 1) {
    echo "Lots of important stuff.";
}</pre>

<p>To many that may look fine, and in fact this exact type of code is in use all over the web. However, if a server has "register_globals" set to on, then simply adding "?authorized=1" to the URL will give anyone free access to exactly what you do not want everyone to see. This is one of the most common PHP security problems.</p>

<p>Fortunately, this has a couple of possible simple solutions. The first, and perhaps the best, is to set "register_globals" to off. The second is to ensure that you only use variables that you have explicitly set yourself. In the above example, that would mean adding "$authorized = 0;" at the beginning of the script:</p>

<pre class="php">$authorized = 0;
if ($password == "my_password") {
    $authorized = 1;
}

if ($authorized == 1) {
    echo "Lots of important stuff.";
}</pre>

<h3>Error Messages</h3>

<p>Errors are a very useful tool for both programmer and hacker. A developer needs them in order to fix bugs. A hacker can use them to find out all sorts of information about a site, from the directory structure of the server to database login information. If possible, it is best to turn off all error reporting in a live application. PHP can be told to do this through .htaccess or php.ini, by setting "error_reporting" to "0". If you have a development environment, you can set a different error reporting level for that.</p>

<h3>SQL Injection</h3>

<p>One of PHP's greatest strengths is the ease with which it can communicate with databases, most notably <a href="http://www.mysql.com">MySQL</a>. Many people make extensive use of this, and a great many sites, including this one, rely on databases to function.</p>

<p>However, as you would expect, with that much power there are potentially huge security problems you can face. Fortunately, there are plenty of solutions. The most common security hazard faced when interacting with a database is that of SQL Injection - when a user uses a security glitch to run SQL queries on your database.</p>

<p>Let's use a common example. Many login systems feature a line that looks a lot like this when checking the username and password entered into a form by a user against a database of valid username and password combinations, for example to control access to an administration area:</p>

<pre class="php">$check = mysql_query("SELECT Username, Password, UserLevel FROM Users WHERE Username = '".$_POST['username']."' and Password = '".$_POST['password']."'");</pre>

<p>Look familiar? It may well do. And on the face of it, the above does not look like it could do much damage. But let's say for a moment that I enter the following into the "username" input box in the form and submit it:</p>

<pre class="php">' OR 1=1 #</pre>

<p>The query that is going to be executed will now look like this:</p>

<pre class="sql">SELECT Username, Password FROM Users WHERE Username = '' OR 1=1 #' and Password = ''</pre>

<p>The hash symbol (#) tells MySQL that everything following it is a comment and to ignore it. So it will actually only execute the SQL up to that point. As 1 always equals 1, the SQL will return all of the usernames and passwords from the database. And as the first username and password combination in most user login databases is the admin user, the person who simply entered a few symbols in a username box is now logged in as your website administrator, with the same powers they would have if they actually knew the username and password.</p>

<p>With a little creativity, the above can be exploited further, allowing a user to create their own login account, read credit card numbers or even wipe a database clean.</p>

<p>Fortunately, this type of vulnerability is easy enough to work around. By checking for apostrophes in the items we enter into the database, and removing or neutralising them, we can prevent anyone from running their own SQL code on our database. The function below would do the trick:</p>

<pre class="php">function make_safe($variable) {
    $variable = mysql_real_escape_string(trim($variable));
    return $variable;
}</pre>

<p>Now, to modify our query. Instead of using _POST variables as in the query above, we now run all user data through the make_safe function, resulting in the following code:</p>

<pre class="php">$username = make_safe($_POST['username']);
$password = make_safe($_POST['password']);
$check = mysql_query("SELECT Username, Password, UserLevel FROM Users WHERE Username = '".$username."' and Password = '".$password."'");</pre>

<p>Now, if a user entered the malicious data above, the query will look like the following, which is perfectly harmless. The following query will select from a database where the username is equal to "\' OR 1=1 #".</p>

<pre class="sql">SELECT Username, Password, UserLevel FROM Users WHERE Username = '\' OR 1=1 #' and Password = ''</pre>

<p>Now, unless you happen to have a user with a very unusual username and a blank password, your malicious attacker will not be able to do any damage at all. It is important to check all data passed to your database like this, however secure you think it is. HTTP Headers sent from the user can be faked. Their referral address can be faked. Their browsers User Agent string can be faked. Do not trust a single piece of data sent by the user, though, and you will be fine.</p>

<h3>File Manipulation</h3>

<p>Some sites currently running on the web today have URLs that look like this:</p>

<pre class="php">index.php?page=contactus.html</pre>

<p>The "index.php" file then simply includes the "contactus.html" file, and the site appears to work. However, the user can very easily change the "contactus.html" bit to anything they like. For example, if you are using <a href="http://www.apache.org/">Apache</a>'s mod_auth to protect files and have saved your password in a file named ".htpasswd" (the conventional name), then if a user were to visit the following address, the script would output your username and password:</p>

<pre class="php">index.php?page=.htpasswd</pre>

<p>By changing the URL, on some systems, to reference a file on another server, they could even run PHP that they have written on your site. Scared? You should be. Fortunately, again, this is reasonably easy to protect against. First, make sure you have correctly set "open_basedir" in your php.ini file, and have set "allow_url_fopen" to "off". That will prevent most of these kinds of attacks by preventing the inclusion of remote files and system files. Next, if you can, check the file requested against a list of valid files. If you limit the files that can be accessed using this script, you will save yourself a lot of aggravation later.</p>

<h3>Using Defaults</h3>

<p>When MySQL is installed, it uses a default username of "root" and blank password. SQL Server uses "sa" as the default user with a blank password. If someone finds the address of your database server and wants to try to log in, these are the first combinations they will try. If you have not set a different password (and ideally username as well) than the default, then you may well wake up one morning to find your database has been wiped and all your customers' credit card numbers stolen. The same applies to all software you use - if software comes with default username or password, change them.</p>

<h3>Leaving Installation Files Online</h3>

<p>Many PHP programs come with installation files. Many of these are self-deleting once run, and many applications will refuse to run until you delete the installation files. Many however, will not pay the blindest bit of attention if the install files are still online. If they are still online, they may still be usable, and someone may be able to use them to overwrite your entire site.</p>

<h3>Predictability</h3>

<p>Let us imagine for a second that your site has attracted the attention of a Bad Person. This Bad Person wants to break in to your administration area, and change all of your product descriptions to "This Product Sucks". I would hazard a guess that their first step will be to go to http://www.yoursite.com/admin/ - just in case it exists. Placing your sensitive files and folders somewhere predictable like that makes life for potential hackers that little bit easier.</p>

<p>With this in mind, make sure you name your sensitive files and folders so that they are tough to guess. Placing your admin area at http://www.yoursite.com/jsfh8sfsifuhsi8392/ might make it harder to just type in quickly, but it adds an extra layer of security to your site. Pick something memorable by all means if you need an address you can remember quickly, but don't pick "admin" or "administration" (or your username or password). Pick something unusual.</p>

<p>The same applies to usernames and passwords. If you have an admin area, do not use "admin" as the username and "password" as the password. Pick something unusual, ideally with both letters and numbers (some hackers use something called a "dictionary attack", trying every word in a dictionary as a password until they find a word that works - adding a couple of digits to the end of a password renders this type of attack useless). It is also wise to change your password fairly regularly (every month or two).</p>

<p>Finally, make sure that your error messages give nothing away. If your admin area gives an error message saying "Unknown Username" when a bad username is entered and "Wrong Password" when the wrong password is entered, a malicious user will know when they've managed to guess a valid username. Using a generic "Login Error" error message for both of the above means that a malicious user will have no idea if it is the username or password he has entered that is wrong.</p>

<h3>Finally, Be Completely and Utterly Paranoid</h3>

<p>If you assume your site will never come under attack, or face any problems of any sort, then when something eventually does go wrong, you will be in massive amounts of trouble. If, on the other hand, you assume every single visitor to your site is out to get you and you are permanently at war, you will help yourself to keep your site secure, and be prepared in case things should go wrong.</p>

<p><em>Ready for more? Try <a href="http://www.addedbytes.com/security/writing-secure-php-2/">Writing Secure PHP, Part 2</a>.</em></p> <br><br>]]></description>
				<pubDate>Fri, 16 Jul 2004 09:07:15 +0000</pubDate>
				<guid isPermaLink="false">http://www.addedbytes.com/writing-secure-php/writing-secure-php-1/</guid>
				<dc:creator>Dave Child</dc:creator>
				<a href="/feeds/tag-feed/?tags=code&amp;start=0" class="ditto_tag" rel="tag">code</a>,<a href="/feeds/tag-feed/?tags=coding&amp;start=0" class="ditto_tag" rel="tag">coding</a>,<a href="/feeds/tag-feed/?tags=development&amp;start=0" class="ditto_tag" rel="tag">development</a>,<a href="/feeds/tag-feed/?tags=mysql&amp;start=0" class="ditto_tag" rel="tag">mysql</a>,<a href="/feeds/tag-feed/?tags=php&amp;start=0" class="ditto_tag" rel="tag">php</a>,<a href="/feeds/tag-feed/?tags=programming&amp;start=0" class="ditto_tag" rel="tag">programming</a>,<a href="/feeds/tag-feed/?tags=security&amp;start=0" class="ditto_tag" rel="tag">security</a>,<a href="/feeds/tag-feed/?tags=tips&amp;start=0" class="ditto_tag" rel="tag">tips</a>,<a href="/feeds/tag-feed/?tags=tutorial&amp;start=0" class="ditto_tag" rel="tag">tutorial</a>,<a href="/feeds/tag-feed/?tags=web&amp;start=0" class="ditto_tag" rel="tag">web</a>,<a href="/feeds/tag-feed/?tags=webdesign&amp;start=0" class="ditto_tag" rel="tag">webdesign</a>,<a href="/feeds/tag-feed/?tags=webdev&amp;start=0" class="ditto_tag" rel="tag">webdev</a>
			</item>

			<item>
				<title>The Box Model For Beginners</title>
				<link>http://www.addedbytes.com/for-beginners/the-box-model-for-beginners/</link>
				<description><![CDATA[ An explanation of what the box model is and how it is treated by different user agents. <p>The term "box model" is often used by people when talking about CSS-based layouts and design. Not everyone understands what is meant by this though, and not everyone understands why it is so important.</p>

<p>Any HTML element can be considered a box, and so the box model applies to all HTML (and XHTML) elements.</p>

<p>The box model is the specification that defines how a box and its attributes relate to each other. In its simplest form, the box model tells browsers that a box defined as having width 100 pixels and height 50 pixels should be drawn 100 pixels wide and 50 pixels tall.</p>

<p>There is more you can add to a box, though, like padding, margins, borders, etc. This image should help explain what I'm about to run through:</p>

<p style="text-align:center;"><img src="content/box-model/box.png" alt="Outline of box model" /></p>

<p>As you can see, a box is made up of four distinct parts. The outside one, the margin, is completely invisible. It has no background color, and will not obstruct elements behind it. The margin is outside the second part, which is the border. The border outlines the visible portion of the element. Inside the border is the third part of the box, the padding, and then inside that the content area of the box. The padding defines the space between the content area of the box and the border.</p>

<p>(Note that in the image above, the only border of the three drawn that would actually be visible is the solid line - the dashed lines are added to help demonstrate the box model).</p>

<p>When you define a width and a height for your box using CSS, you are defining not the entire area taken up by the content, padding, border and margin. You are actually just defining the content area itself - the bit right in the middle. The padding, border and margin must be added to that in order to calculate the total space occupied by the box. (From this point on, we will use width for demonstrations, but the same principles apply to both width and height).</p>

<code>box {
    width: 200px;
    border: 10px solid #99c;
    padding: 20px;
    margin: 20px;
}</code>

<p>The above CSS, applied to a box, would mean that that box occupied 300 pixels of space horizontally on the page. The content of the box would occupy 200 pixels of that (dashed line added to demonstrate the edge of the area occupied by the box):</p>

<p style="text-align:center;"><img src="content/box-model/box_demo.png" alt="Box model demonstration." /></p>

<p>In the above image, you can see that the pale blue area is 240 pixels wide (200 pixels of content plus 20 pixels padding either side). The border is 10 pixels wide either side, making the total width including the border 260 pixels. The margin is 20 pixels either side, making the total width of the box 300 pixels.</p>

<p>In practice, this can cause some confusion. For example, if I have a 100 pixel wide space available, and want to fill it with a pale red box with a dark red border and a small amount of padding, it would be very easy to write the CSS like so:</p>

<code>box {
    width: 100px;
    border: 1px solid #900;
    padding: 10px;
    margin: 0;
    background: #fee;
}</code>

<p>(A declaration of 0, as used for the margin above, does not require a unit to be added. Any value other than 0 does require a unit, e.g. px for pixels. Also, although "background" is defined as a shorthand property, it is more widely supported than the more correct "background-color".)</p>

<p>However, that will not give us a 100 pixel wide box, as the width declaration defines the content area of the box. The content area of the box will be 100 pixels - the total width of the box as defined above will be 122 pixels:</p>

<p style="text-align:center;"><img src="content/box-model/box_demo2.png" alt="Box model demonstration." /></p>

<p>In order to set the above box to only occupy 100 pixels horizontally, you would need to set the width of the content area to be 100 pixels minus the padding and minus the border, in this case 78 pixels, like so:</p>

<code>box {
    width: <strong>78px</strong>;
    border: 1px solid #900;
    padding: 10px;
    margin: 0;
    background: #fee;
}</code>

<p>To calculate the overall width of a box, including all padding, borders and margins, you would use the following formula:</p>

<code>total box width = content area width + left padding + right padding + left border + right border + left margin + right margin</code>

<h3>Compatibility</h3>

<p>At this point, you should now have a good understanding of what the box model is, and how boxes <em>should</em> be treated by different browsers. However, as you will soon learn (if you did not know already), not every browser does as it is supposed to. In order to use boxes, and by extension make the most of CSS in your website, you will need to be aware of how the different browsers treat boxes in practice and how to overcome and work around the problems presented by these idiosyncrasies.</p>

<h3>Top Notch</h3>

<p><img src="images/browser_logos/opera6.gif" alt="Opera 6" /> <img src="images/browser_logos/opera7.gif" alt="Opera 7" /> <img src="images/browser_logos/mozilla.gif" alt="Mozilla" /> <img src="images/browser_logos/firefox.gif" alt="Firefox" /> <img src="images/browser_logos/camino.gif" alt="Camino" /> <img src="images/browser_logos/safari.gif" alt="Safari" /> <img src="images/browser_logos/konqueror.gif" alt="Konqueror" /> <img src="images/browser_logos/netscape6.gif" alt="Netscape 6" /> <img src="images/browser_logos/netscape7.gif" alt="Netscape 7" /> <img src="images/browser_logos/ie6.gif" alt="Internet Explorer 6" /></p>

<p>Most browsers released in the last few years have no problem with boxes and render boxes correctly. Opera 6 and 7, Mozilla 1 (and by extension other browsers based on the Gecko engine like Netscape 7, Camino and Firefox and other derivatives), Safari, Konquerer (and derivatives) and Internet Explorer 5 for the Mac are all shining examples of how a web browser <em>should</em> behave, all rendering boxes flawlessly. IE 6 for Windows also will render a box correctly, as long as the [url=http://www.addedbytes.com/design/dtds-explained]Document Type Definition[/url] for the page is correct.</p>

<h3>Whoops, Mrs Miggins, You're Sitting On My Artichokes</h3>

<p><img src="images/browser_logos/ie5.gif" alt="Internet Explorer 5" /> <img src="images/browser_logos/ie6.gif" alt="Internet Explorer 6" /></p>

<p>Some browsers don't display a box correctly. Unlike those below here, these browsers are widely enough used on the web that it is usually worth the effort to work through the problem. There are various methods for doing this, some better than others, that follow on. Most notable among the browsers with problems are Internet Explorers 4 and 5 and Internet Explorer 6. IE 6 is easy to work around, by adding a correct DTD (which you should be doing anyway).</p>

<p>Internet Explorer 5 is the main reason there is a box model problem at all. It, unfortunately, does not follow the simple definition for box layout as defined by the W3c. When you define a width for a box and it is rendered in IE5, instead of that width defining the content area of the box, it <em>includes the borders and padding</em>. Margins are added on to the content width correctly, but padding and borders are not. Unfortunately, this leaves us with some unpleasant choices:</p>

<ol><li><strong>Use a box model hack</strong><br />
Hack's like [url=http://www.tantek.com/CSS/Examples/boxmodelhack.html]Tantek's box model hack[/url] are unfortunately something of a necessity. While some might argue that using hacks like this is completely missing the point of using CSS for web design, commercial necessity and the prevalence of IE5 leave us with little in the way of choice. The IE5 box model hack is in use all over the web and has spawned plenty of variants.</li><li><strong>Add in extra code</strong><br />
Some might consider this a slightly "better" way of working around this problem. Rather than adding a style sheet hack, you can nest elements within each other. Adding a div within another div means that rather than using padding, you can use just margins, which are handled correctly by IE5. As with the box model hack, it is far from a perfect solution, but there are few other options if you want a site to look the same in IE5 as other more capable browsers.</li></ol>

<h3>Hall of Shame</h3>

<p><img src="images/browser_logos/ie4.gif" alt="Internet Explorer 4" /> <img src="images/browser_logos/netscape4.gif" alt="Netscape 4" /></p>

<p>On the one hand, the browsers that I am about to mention are appalling, all failing dismally to render a simple box correctly for one reason or another. On a more positive note, users of these browsers, mostly old versions of current browsers, make up an extremely small, and continually shrinking, portion of web users. While you could probably find a workaround for the bugs in the display of boxes in these browsers, it is almost certainly not worth the effort - you are likely to cause yourself more harm than good with workarounds for these!</p>

<p>Netscape 4's box model is awful, but even worse, the simple box model hacks to fix the problem for IE5 and IE6 will crash Netscape 4. Netscape 4's style sheet support is abysmal overall, and it is being supported less and less. Though it is strictly a personal choice, I don't think it is worth the time and effort to support Netscape 4 any more - it's just not used enough, and the number of users is only ever going to shrink.</p>

<p>Internet Explorer 4 suffers, basically, the same problem as IE5. It treats boxes in a very similar way. However, it falls over in far more ways, and many of the available hacks will crash IE4. As it is also used by few people, and that number is dropping, many designers ignore it.</p>

<h3>What does the future hold?</h3>

<p>CSS3 promises us the option to determine how we want the user agent to treat boxes, and specify which box model we want to use. Support for CSS3 at a level that will be possible is many many years away yet. Until then, we are stuck with the CSS2 box model, and while IE5 is still used by a significant percentage of the web's population, we are going to have problems with boxes.</p> <br><br>]]></description>
				<pubDate>Fri, 09 Jul 2004 10:48:54 +0000</pubDate>
				<guid isPermaLink="false">http://www.addedbytes.com/for-beginners/the-box-model-for-beginners/</guid>
				<dc:creator>Dave Child</dc:creator>
				<a href="/feeds/tag-feed/?tags=box&amp;start=0" class="ditto_tag" rel="tag">box</a>,<a href="/feeds/tag-feed/?tags=boxmodel&amp;start=0" class="ditto_tag" rel="tag">boxmodel</a>,<a href="/feeds/tag-feed/?tags=css&amp;start=0" class="ditto_tag" rel="tag">css</a>,<a href="/feeds/tag-feed/?tags=design&amp;start=0" class="ditto_tag" rel="tag">design</a>,<a href="/feeds/tag-feed/?tags=html&amp;start=0" class="ditto_tag" rel="tag">html</a>,<a href="/feeds/tag-feed/?tags=model&amp;start=0" class="ditto_tag" rel="tag">model</a>,<a href="/feeds/tag-feed/?tags=reference&amp;start=0" class="ditto_tag" rel="tag">reference</a>,<a href="/feeds/tag-feed/?tags=tips&amp;start=0" class="ditto_tag" rel="tag">tips</a>,<a href="/feeds/tag-feed/?tags=tutorial&amp;start=0" class="ditto_tag" rel="tag">tutorial</a>,<a href="/feeds/tag-feed/?tags=webdesign&amp;start=0" class="ditto_tag" rel="tag">webdesign</a>,<a href="/feeds/tag-feed/?tags=webdev&amp;start=0" class="ditto_tag" rel="tag">webdev</a>
			</item>

			<item>
				<title>Output Caching for Beginners</title>
				<link>http://www.addedbytes.com/for-beginners/output-caching-for-beginners/</link>
				<description><![CDATA[ High-traffic sites can often benefit from caching of pages, to save processing of the same data over and over again. This caching tutorial runs through the basics of file caching in PHP. <p>Caching of output in PHP is made easier by the use of the output buffering functions built in to PHP 4 and above.</p>

<p>You'll need to use two files to set up a caching system for your site. The first, "begin_caching.php" in this case, will run before any other PHP on your site. The second, "end_caching.php" in this case, runs after normal scripts have run. The two scripts effectively wrap around your current site.</p>

<p>You can achieve this wrapping effect one of two ways. The first way is to simply use the include() function and add them manually to every script you run. Unfortunately, this method can take some time, but is arguably more portable than the alternative.</p>

<p>The alternative relies on adding the following two lines of code (modified to reflect the correct path to the two PHP files needed) to your htaccess file. This is my preferred method, just because it requires no modification to existing scripts, and can very easily and quickly be turned off (just by commenting out the relevant lines in the htaccess file).</p>

<pre class="php">php_value auto_prepend_file /full/path/to/begin_caching.php
php_value auto_append_file /full/path/to/end_caching.php</pre>

<p>Next, we move on to the scripts that do the work. There are several stages to caching a document:</p>

<ol><li>Receive request for page</li><li>Check for the existence of a cached version of that page</li><li>Check the cached copy is still valid<ul><li>If it is, send the cached copy</li><li>If not, create a new cached copy and send it</li></ul></li></ol>

<p>To begin with, the script below contains a few basic settings. Here, you can set the directory you want to save cached files to (I would recommend keeping that directory outside your web root directory or at least protecting it from view through a normal browser). This script will need to be able to create files in this directory, and you need to allow this by setting the permissions of the directory. The permissions depend upon your server set up, so you may want to start by setting them to 777 while testing the script, and then reduce them to the lowest levels possible once the script is working.</p>

<p>You can also set the time, in seconds, a cached file should be considered valid for after creation, and set the file extension for saved files. It would be wise to not name them ".php", just for safety's sake.</p>

<pre class="php">&lt;?php

    // Settings
    $cachedir = '../cache/'; // Directory to cache files in (keep outside web root)
    $cachetime = 600; // Seconds to cache files for
    $cacheext = 'cache'; // Extension to give cached files (usually cache, htm, txt)

    // Ignore List
    $ignore_list = array(
        'addedbytes.com/rss.php',
        'addedbytes.com/search/'
    );

    // Script
    $page = 'http://' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI']; // Requested page
    $cachefile = $cachedir . md5($page) . '.' . $cacheext; // Cache file to either load or create

    $ignore_page = false;
    for ($i = 0; $i &lt; count($ignore_list); $i++) {
        $ignore_page = (strpos($page, $ignore_list[$i]) !== false) ? true : $ignore_page;
    }

    $cachefile_created = ((@file_exists($cachefile)) and ($ignore_page === false)) ? @filemtime($cachefile) : 0;
    @clearstatcache();

    // Show file from cache if still valid
    if (time() - $cachetime &lt; $cachefile_created) {

        <em>//ob_start('ob_gzhandler');</em>
        @readfile($cachefile);
        <em>//ob_end_flush();</em>
        exit();

    }

    // If we're still here, we need to generate a cache file

    ob_start();

?&gt;</pre>

<p>The file starts by generating an MD5 hash of the page that has been requested. It will use the complete requested URL, and the MD5 hash will be a 32 digit number, unique for each file. It then checks for the existence of this file.</p>

<p>If the file exists, it checks to see when it was last updated. If the file is older than the allowed time, it acts as though no cache existed (carrying on and generating a new file). If the file is still valid, it simply displays it.</p>

<p>There is also, in the settings, a list of pages to ignore when caching. This can be search results, comments pages, a news page or news feed - anything that should always be up to date. Simply add anything you do not want cached into here, and it will not be cached. You can add directories, or parts of URLs - the above simply searches for a text string. In the example above, I have left out the "http://www" portion of the URL, as this can be missed out by some visitors.</p>

<p>Finally, the two lines in italics above are both commented out. You can, if you like, uncomment these, and that will use outbut buffering to gzip your content before sending it to users, making your site even faster for them. Please note, though, that output buffering with gz encoding is not available in versions of PHP previous to 4.0.5.</p>

<p>Which brings us to the second file, "end_caching.php". At the end of the first file, if no cache exists, we start output buffering. This means that rather than send the page to the user, we are saving it for use later. In the second script below, we take the contents of the output buffer, and write it to a file.</p>

<pre class="php">&lt;?php

    // Now the script has run, generate a new cache file
    $fp = @fopen($cachefile, 'w'); 

    // save the contents of output buffer to the file
    @fwrite($fp, ob_get_contents());
    @fclose($fp); 

    ob_end_flush(); 

?&gt;</pre>

<p><strong>Important:</strong> If you do not have "register_globals" set to off in php.ini, make sure you add the following to the beginning of "end_caching.php" (straight after the "&lt;?php" line) to aid security. This will ensure that an attacker cannot visit "end_caching.php" directly and overwrite an important file on your site (or read its contents).</p>

<pre class="php">    $cachedir = '../cache/'; // Directory to cache files in (keep outside web root)
    $cacheext = 'cache'; // Extension to give cached files (usually cache, htm, txt)
    $page = 'http://' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI']; // Requested page
    $cachefile = $cachedir . md5($page) . '.' . $cacheext; // Cache file to either load or create</pre>

<p>And there we have it. If a cached document exists, it is shown to the user, and if not, one is created.</p>

<p>Finally, you need to make sure the cache remains reasonably clean. Over time, out of date or redundant files could build up, and these should be removed regularly. For this reason, I usually set up an automated script to delete all cache files once a week (or less often, depending on the traffic of the site), but this will depend greatly upon the server software you are using.</p>

<p>The script below is one example of a script to delete all cache files. You will need to set the cache directory at the beginning before running the script. You can either use this manually, visiting the page through your browser whenever you want to empty the cache, or run it automatically. An example of a CRON job used to run this script automatically is below the script (the " &gt;/dev/null 2&gt;&amp;1" bit at the end of the crontab prevents the server emailing me every time the script runs). Please note that this last script will be cached too, unless you specify otherwise!</p>

<pre class="php">&lt;?php

    // Settings
    $cachedir = '../cache/'; // Directory to cache files in (keep outside web root)

    if ($handle = @opendir($cachedir)) {
        while (false !== ($file = @readdir($handle))) {
            if ($file != '.' and $file != '..') {
                echo $file . ' deleted.&lt;br&gt;';
                @unlink($cachedir . '/' . $file);
            }
        }
        @closedir($handle);
    }

?&gt;</pre>

<pre class="php">curl http://www.your_domain.com/empty_caching.php &gt;/dev/null 2&gt;&amp;1</pre> <br><br>]]></description>
				<pubDate>Wed, 09 Jun 2004 15:13:00 +0000</pubDate>
				<guid isPermaLink="false">http://www.addedbytes.com/for-beginners/output-caching-for-beginners/</guid>
				<dc:creator>Dave Child</dc:creator>
				<a href="/feeds/tag-feed/?tags=article&amp;start=0" class="ditto_tag" rel="tag">article</a>,<a href="/feeds/tag-feed/?tags=cache&amp;start=0" class="ditto_tag" rel="tag">cache</a>,<a href="/feeds/tag-feed/?tags=caching&amp;start=0" class="ditto_tag" rel="tag">caching</a>,<a href="/feeds/tag-feed/?tags=code&amp;start=0" class="ditto_tag" rel="tag">code</a>,<a href="/feeds/tag-feed/?tags=development&amp;start=0" class="ditto_tag" rel="tag">development</a>,<a href="/feeds/tag-feed/?tags=performance&amp;start=0" class="ditto_tag" rel="tag">performance</a>,<a href="/feeds/tag-feed/?tags=php&amp;start=0" class="ditto_tag" rel="tag">php</a>,<a href="/feeds/tag-feed/?tags=programming&amp;start=0" class="ditto_tag" rel="tag">programming</a>,<a href="/feeds/tag-feed/?tags=tutorial&amp;start=0" class="ditto_tag" rel="tag">tutorial</a>,<a href="/feeds/tag-feed/?tags=web&amp;start=0" class="ditto_tag" rel="tag">web</a>,<a href="/feeds/tag-feed/?tags=webdev&amp;start=0" class="ditto_tag" rel="tag">webdev</a>
			</item>

			<item>
				<title>CSS Selectors for Beginners</title>
				<link>http://www.addedbytes.com/for-beginners/css-selectors-for-beginners/</link>
				<description><![CDATA[ CSS Selectors allow you to specify the types and groups of elements you want to apply certain styles to. <p>Selectors are a tool within CSS that allow you to ensure that a style is only applied to a set page element, of group of them. In its simplest form, a selector can be simply a tag name. For example, you may have a rule on a web page that looks like this:</p>

<code>h1 {
    font-weight: bold;
    font-size: 1.5em;
    color: #f00;
}</code>

<p>The above will turn all text within &lt;h1&gt; tags large, bold and red. The start of the rule, "h1", tells the user agent to only apply that rule, the large bold redness, to text within &lt;h1&gt; tags. This is a part of CSS1, the first level of CSS. Any browser that supports CSS at all should support basic selectors like these.</p>

<p>However, while the above is useful, it doesn't let you apply styles very specifically to individual elements, or to only a small subset of items of one type, or group. So next, we have classes and ids, used within code to allow us to apply styles to, respectively, elements of a specific group, and unique single elements on a page. You apply these by adding "class" and "id" attributes to the HTML of your document, and then adding selectors to the CSS, like so:</p>

<code>&lt;html&gt;
    &lt;head&gt;
        &lt;style type="text/css"&gt;&lt;!--

            p {
                font-size: 0.8em;
            }

            .main_text {
                color: #f00;
            }

            #first_paragraph {
                font-weight: bold;
            }

        --&gt;&lt;/style&gt;
    &lt;/head&gt;
    &lt;body&gt;

        &lt;p id="first_paragraph" class="main_text"&gt;
            Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
        &lt;/p&gt;

        &lt;p  class="main_text"&gt;
            Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
        &lt;/p&gt;

        &lt;p&gt;
            Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
        &lt;/p&gt;

    &lt;/body&gt;
&lt;/html&gt;</code>

<p>The first selector in the CSS tells the browser that the following style applies to all text within "&lt;p&gt;" tags. The second rule starts with the selector ".main_text", telling the browser that the following rule applies to all elements of class "main_text", the "." telling the browser this rule applies to a class, and the "main_text" identifying that class. The third rules starts with the selector "#first_paragraph". The "#" at the beginning tells the browser that the rule only applies to one element, with the id "first_paragraph".</p>

<p>Again, the above is a part of CSS1, and should be supported by any browser with basic CSS support.</p>

<p>If you want, you can apply styles to elements depending upon their position within a page. For example, if you want to apply styling to any list item in an unordered list, but not ordered lists, you can write a CSS rule like so:</p>

<code>ul li {
    font-weight: bold;
}</code>

<p>The above will make any list item within an unordered list bold. This type of selector, where the style is applies to a specific descendant of an element within the code, will be supported by most browsers with any CSS support, the notable exception being Netscape Navigator 4, which does not understand descendant selectors.</p>

<p>Selectors can be combined as well. For example, if you wanted to apply a style to links within an unordered list, and make one stand out, the following CSS and HTML would do the job admirably:</p>

<code>&lt;html&gt;
    &lt;head&gt;
        &lt;style type="text/css"&gt;&lt;!--

            ul a {
                color: #f00;
            }

            ul #unique {
                font-weight: bold;
            }

        --&gt;&lt;/style&gt;
    &lt;/head&gt;
    &lt;body&gt;

        &lt;ul&gt;

            &lt;li&gt;
                &lt;a&gt;First link&lt;/a&gt;
            &lt;/li&gt;

            &lt;li&gt;
                &lt;a&gt;Second link&lt;/a&gt;
            &lt;/li&gt;

            &lt;li&gt;
                &lt;a id="unique"&gt;Unique link&lt;/a&gt;
            &lt;/li&gt;

        &lt;/ul&gt;

    &lt;/body&gt;
&lt;/html&gt;</code>

<p>The above will set all links within the list to red, then the link with the id "unique" to bold.</p>

<p>And there you have the basic CSS selectors. Beleive it or not, the simple rules above, when combined (and together with a few creative styles) can create amazing looks for sites with just a few lines of code.</p> <br><br>]]></description>
				<pubDate>Mon, 17 May 2004 12:05:58 +0000</pubDate>
				<guid isPermaLink="false">http://www.addedbytes.com/for-beginners/css-selectors-for-beginners/</guid>
				<dc:creator>Dave Child</dc:creator>
				<a href="/feeds/tag-feed/?tags=css&amp;start=0" class="ditto_tag" rel="tag">css</a>,<a href="/feeds/tag-feed/?tags=tutorial&amp;start=0" class="ditto_tag" rel="tag">tutorial</a>
			</item>

			<item>
				<title>PHP for Beginners</title>
				<link>http://www.addedbytes.com/for-beginners/php-for-beginners/</link>
				<description><![CDATA[ An introduction to PHP, one of the most popular programming languages on the web. <p>PHP stands for PHP: Hypertext Preprocessor (yes, it is a recursive acronym, in that PHP is one of the words of the acronym), and is a scripting language that can usually be found running on Apache servers. It is an Open Source language (for more information about Open Source, visit <a href="http://www.opensource.org/">OpenSource.org</a>). It is very powerful, and very easy to learn, which along with the fact it runs on Apache (Open Source) and is itself Open Source makes it one of the most popular scripting languages in use on the web today.</p>

<p>There are several versions of PHP, the current one being PHP 4, though at the time of writing PHP 5 is due for imminent release.</p>

<p>PHP pages usually end with the extension ".php", ".phtml" or ".php3", for example "index.php". Pages that have a recognised extension, on a properly configured server, will be processed by the PHP scripting engine before being returned to the user. Anything within the tags '&lt;?php' and '?&gt;' is code and will be processed by the engine.</p>

<p>Which brings us neatly to our first piece of code. The first thing you will learn to do with PHP is use it to write a simple piece of text to a web page (the famous "Hello World").</p>

<pre class="php">&lt;html&gt;
    &lt;body&gt;
        &lt;?php
            echo 'Hello World!';
        ?&gt;
    &lt;/body&gt;
&lt;/html&gt;</pre>

<p>Copy and paste the above to an empty text file (for example in Notepad). Save it as "php101.php", and upload it to a server that supports PHP. When you load the page in a browser, you should see the text "Hello World!". If you do, congratulations! You've finished your first script. If not, it may be that your server does not support PHP - the above should work on any server with PHP support.</p>

<p>What you have done in the above example is write out a normal HTML page, but you have used the PHP scripting engine to write out the text within the page. A good start, but not the most useful of tools so far. Next, we'll learn how to use basic variables.</p>

<p>Variables in PHP are very easy to use. You can spot a variable, because its name will almost always begin with a "$" sign. It is always a good idea to name your variables so that you can see easily what they refer to. For example, a variable containing a first name might be called "$FirstName".</p>

<p>To use these in a script is reasonably simple:</p>

<pre class="php">&lt;html&gt;
    &lt;body&gt;
        &lt;?php
            $HelloWorld = 'Hello World, Again!';
            echo $HelloWorld;
        ?&gt;
    &lt;/body&gt;
&lt;/html&gt;</pre>

<p>Note that when you use the variable with the "echo" section, you should not put quotation marks around it. If you do, the script will just write out "$HelloWorld" as text, rather than writing the value you gave it.</p>

<p>The above is a simple process - a variable is created and assigned the value "Hello World, Again!" and written out to the web page. If you copy and paste the above as before, and upload the new script and open it in a browser, you should now see the text "Hello World, Again!" on the page. If you do, congratulations, you have just finished your second PHP script.</p>

<p>Still, though, not the most impressive piece of interaction on the web. Next though, we're going to write a more complex script. This time, we're going to create a variable, give it a value of the current hour of the day, and display a piece of text based upon whether it is morning or afternoon.</p>

<pre class="php">&lt;html&gt;
    &lt;body&gt;
        &lt;?php
            $HourOfDay = date("G");
            if ($HourOfDay &lt; 12) {
                echo 'Good Morning World!&lt;br&gt;&lt;br&gt;The hour of the day is ' . $HourOfDay;
            } else {
                echo 'Good Afternoon World!&lt;br&gt;&lt;br&gt;The hour of the day is ' . $HourOfDay;
            }
        ?&gt;
    &lt;/body&gt;
&lt;/html&gt;</pre>

<p>First, we grab the current time using the "date()" function. The argument, "G" (an argument is a value you pass a function) tells the date function to give us the hour of the day, with leading zeroes. At this stage, $HourOfDay will contain a number representing the hour of the current day.</p>

<p>Next, we check the value. If the value is less than 12, we know the current time is morning, and write out an appropriate greeting, followed by the hour of the day (you use a period to write more than one thing to a page at once). Otherwise (else) it is afternoon, and we write out a different greeting.</p>

<p>Now, to use this, you simply need to upload this script, as before, to your web server, and open it in a web browser. Your server may be on a different time zone to you, but you can see what hour of the day it thinks it is underneath the greeting. What you should now see is a greeting of either "Good Morning World!" or "Good Afternoon World!" followed by a blank line, then the hour of the day.</p>

<p>And voila - your first piece of interactive web programming. Congratulations, you've taken your first steps in PHP!</p> <br><br>]]></description>
				<pubDate>Thu, 13 May 2004 09:29:28 +0000</pubDate>
				<guid isPermaLink="false">http://www.addedbytes.com/for-beginners/php-for-beginners/</guid>
				<dc:creator>Dave Child</dc:creator>
				<a href="/feeds/tag-feed/?tags=php&amp;start=0" class="ditto_tag" rel="tag">php</a>,<a href="/feeds/tag-feed/?tags=tutorial&amp;start=0" class="ditto_tag" rel="tag">tutorial</a>
			</item>
	</channel>
</rss>
