<?xml version="1.0" encoding="utf-8"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
<channel>
<atom:link href="http://www.populate.it/developers_blog.rss" rel="self" type="application/rss+xml" /><title><![CDATA[Developers Blog]]></title>
<link>http://www.populate.it/developer_blogs.html</link>
<description><![CDATA[]]></description>
<item>
<title><![CDATA[Calculating an age on a given date with php]]></title>
<link>http://www.populate.it/age_on_date_php.html</link>
<guid>http://www.populate.it/age_on_date_php.html</guid>
<description><![CDATA[<div>I needed to calculate an age on a given date recently and it takes more thought than meets the eye. I needed to do this to make sure that on a date booked to do a driving experience the participant was old enough for insurance purposes. It is very easy to work out how many secs, mins and hours old they are however years is more of a problem because of the uneven number of days in each year and month. In the end the solution was fairly simple, but it took a while to get there..!</div>
<div>&nbsp;</div>
<div>&nbsp;</div>
<div>&nbsp;</div>
<pre class="brush: php">
//To get the number of years old someone born on 28th Feb 1971 is on the 1st Jun 2012 use:
list ($yearsOld) = getAgeOnDate (1971, 2, 28, 2012, 6, 1) ;

function getAgeOnDate ($birthYear, $birthMonth, $birthDay, $thisYear, $thisMonth, $thisDay) {
	$yearDiff = $thisYear - $birthYear;
	$monthDiff = $thisMonth - $birthMonth;
	$dayDiff = $thisDay - $birthDay;							
	if ($dayDiff &lt; 0) {
		$monthDiff--;
                // This is the difficult bit...
                // if the days crosses the end of the month
                // You need...                
                // The number of days from the birth day to the end of the birth month
                // Plus 
                // The number of days to this point in the current month

		$dayDiff = cal_days_in_month (CAL_GREGORIAN, $birthMonth, $birthYear) - (-1 * $dayDiff);
	}						
	if ($monthDiff &lt; 0){
		$yearDiff--;
		$monthDiff = 12 - (-1 * $monthDiff);
	}
	return array($yearDiff, $monthDiff, $dayDiff);
}
</pre>
<p>&nbsp;</p>]]></description>
</item>
<item>
<title><![CDATA[Sorting PHP associative arrays]]></title>
<link>http://www.populate.it/php-sort-array-by-key.html</link>
<guid>http://www.populate.it/php-sort-array-by-key.html</guid>
<description><![CDATA[<p>There are times when you cannot sort the the order of a data set as you retrieve it from the database, and you need to sort it in script. The function below I wrote a long time ago but use all of the time.</p>
<p>Simply pass in the array, the array key you want to sort on, e.g.&nbsp;</p>
<pre class="brush: php">
$customerArray = sortArrayByKey ($customerArray, &quot;surname&quot;);</pre>
<p>&nbsp;</p>
<pre class="brush: php">
function sortArrayByKey ($key, $array, $desc=false){
    $sortArray = array();
    $returnArray = array();
    foreach ($array as $index=&gt;$value) {
        $sortArray[$index] = $value[$key];
    }
    asort ($sortArray);
    foreach ($sortArray as $index=&gt;$value) {
        $returnArray[] = $array[$index];
    }
    if ($desc) {
        return $returnArray = array_reverse($returnArray);
    } else {
        return ($returnArray);
    }
}
</pre>]]></description>
</item>
<item>
<title><![CDATA[PHP prepared (parameterized) queries that put data into arrays, avoiding sql injection]]></title>
<link>http://www.populate.it/prepared_query_to_array.html</link>
<guid>http://www.populate.it/prepared_query_to_array.html</guid>
<description><![CDATA[<p>After a recent security audit of one of our sites we had to do a but of recoding. One particular issue was with sql injection into form fields</p>
<p>As a result I've written a couple of functions that extract database data into arrays from prepared or parametirised queries using the following functions</p>
<ul>
    <li>mysqli_prepare</li>
    <li>mysqli_stmt_result_metadata</li>
    <li>mysqli_stmt_bind_param</li>
    <li>mysqli_stmt_execute</li>
    <li>mysqli_stmt_bind_result</li>
    <li>mysqli_stmt_fetch</li>
    <li>mysqli_stmt_close</li>
</ul>
<p>If this page gets any hits, comments or feedback I'll add some more detail.</p>
<pre class="brush: php">
		
	
	dbConnect ($dbA);
	
	$unsafeInput = $_POST['input_field'];
	$userArray = $dbA->retrieveAllRecordsFromPreparedQuery ("select * from users where name like ? or address like ?", array ("%".$unsafeInput."%", "%".$unsafeInput."%"));
	print_r ($userArray); // use the array here

	$unsafeInput_1 = $_POST['input_field_1'];
	$unsafeInput_2 = $_POST['input_field_2'];
	$unsafeInput_3 = $_POST['input_field_3'];
	$userArray = $dbA->retrieveAllRecordsFromPreparedQuery ("select * from students where forename like ? or surname like ? or postcode like ?", array ("%".$unsafeInput_1."%", "%".$unsafeInput_2."%", "%".$unsafeInput_3."%");
	print_r ($userArray); // use the array here

	function dbConnect(&$dbA) {
		global $dbHost,$dbUser,$dbPassword,$dbName;
		
		$dbA = new dbAccess();		
		$dbStatus = $dbA-> connect($dbHost,$dbUser,$dbPassword,$dbName);
		
		if ($dbStatus == false && $showErrorOnFail==true) {
			exit;
		}
		return ($dbStatus);
	}

	class dbAccess {
		function connect($sql_host_name,$sql_username,$sql_password,$sql_database_name) {
			$this->currentDatabase = $sql_database_name;
			$this->resID = @mysqli_connect($sql_host_name,$sql_username,$sql_password);
			if ($this->resID == FALSE) {
				$this->lastError = "Could not connect to mySQL server";
				return FALSE;
			} else {
				if (@mysqli_select_db($this->resID, $sql_database_name)) {
					return TRUE;
				} else {
					return @mysqli_query($this->resID,"create database $sql_database_name");
					return FALSE;
				}
			}
		}
		
		function retrieveAllRecordsFromPreparedQuery ($sql_query, $params){
			if ($preparedStmt = mysqli_prepare($this->resID, $sql_query)) {	
				$paramPattern =  $this->getPreparedParamPattern ($params);				
				call_user_func_array('mysqli_stmt_bind_param', array_merge (array($preparedStmt, $paramPattern), $params));
				mysqli_stmt_execute($preparedStmt);
				
				$meta = mysqli_stmt_result_metadata($preparedStmt);				
				$fieldNames = array();
				while ($field = mysqli_fetch_field($meta)) {
				   $fieldNames[] = $field->name;
				}
				$resultRow = array($preparedStmt);
				foreach($fieldNames as $value) {
					$resultRow[] = &$$value;
				}
				call_user_func_array('mysqli_stmt_bind_result', $resultRow);
				$result = array();
				while(mysqli_stmt_fetch($preparedStmt)) {
					$thisRow = array();
					foreach($fieldNames as $value) {
						$thisRow[$value] = $$value;
					}
					$result[] = $thisRow;
				}
				mysqli_stmt_close($preparedStmt);
				return $result;
			} else {
				return "ERROR";
			}
		}

		function getPreparedParamPattern ($params){	
			$paramPattern = "";			
			foreach ($params as $thisParam) {					
				if (is_string($thisParam)) {
					$paramPattern .= "s";
				} elseif (is_int($thisParam)) {
					$paramPattern .= "i";
				} elseif (is_float($thisParam)) {
					$paramPattern .= "d";
				} else {
					die("invalid prepare type");
				}
			}
			return $paramPattern;
		}
	}
		</pre>]]></description>
</item>
<item>
<title><![CDATA[This page contains both secure and nonsecure items]]></title>
<link>http://www.populate.it/page_contains_both_secure_and_nonsecure_items.html</link>
<guid>http://www.populate.it/page_contains_both_secure_and_nonsecure_items.html</guid>
<description><![CDATA[<p>Have you ever set up an https part of a website and seen the errror:&nbsp;</p>
<p>This page contains both secure and nonsecure items, do you want to display the non-secure?&nbsp;</p>
<p>Explorer shows an alert error which can seriously deter your customers, Chrome and Firefox are a bit more subtle turning the https padlock red in the navigation bar, but again this is pretty off putting to your customers.</p>
<p>The first thing to do is look at your source. All remote files should be linked relatively meaning they will be retrieved using the same protocal as the page (https) this applies to images, external javascript files, external stylesheets, iframe/frame content, flash etc. The only place you see http in your source is in links and forms e.g. paths off of your page. As part of this step mke sure any tracking you are using (Analytics etc) is also using a secure connection. If you suspect that a piece of code is causing the error, temporarily remove the suspect code and refresh the page, if the error has gone away you have found your culprit and need to see the documentation from the tracking provide as there will be a solution.</p>
<p>One thing to point out here is that the different browsers report these problems differently making it harder to resolve the problem is some browsers than others. Chrome especially seems to hang onto the error, caching it up (even after you clear the complete history) making it hard to resolve if the error is fixed or not. Explorer for once seems more reliable here, if the connection is secure - no alert, if its nonsecure - the alert shows.. therefore, for once, explorer is first choice.. However Chrome can be useful in reporting where the insecure content is. open the developer tools (spanner &gt; tools &gt; developer tools) reload the page, and the insecure content is listed.. usually.</p>
<p>Another way to trace the issue is to remove or comment out blocks of code. comment out the whole page the error should go.. gradully reintroduce blocks until the error comes back.</p>
<p>One thing you to be aware of here is redirects. If you have any server side redirects it could take you from a file on https to http without you realising. An example might be an image in your style sheet that doesn't exist and your server redirects the request to a non-secure error page. One way to find these is to see which resources are being requested then call them directly in your browser, if the url is redirected you have found your culprit. Chrome is very good here as viewing source allows you to click the external links..</p>
<p>The reason this issue is in my thoughts at the moment is I have just spent a couple of hours trying to resolve an issue that turned out to be an embdeded swf, the object tag had 'codebase=...' in it removing this stoped the 'nonsecure items' error.&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>]]></description>
</item>
<item>
<title><![CDATA[CSS cross browser fonts using CSS3]]></title>
<link>http://www.populate.it/css_cross_browser_fonts_using_css3.html</link>
<guid>http://www.populate.it/css_cross_browser_fonts_using_css3.html</guid>
<description><![CDATA[<p>&nbsp;</p>
<div>Being able to embed whichever font you wish is the dream of web developers everywhere. No more time consuming excursions into photoshop to cut up page titles or navagation elements. Well, with CSS3 this dream is now a reality... sort of.&nbsp;</div>
<div>&nbsp;</div>
<div>It is actually a very simple job to implement embedded fonts like this :<br />
<br />
<span class="fontTest">I'm an embedded css3 font</span><br />
<span class="fontTestLeague">Another css3 font!</span> <br />
<span class="fontTestBeyond">css is great&nbsp;</span></div>
<pre class="brush: css">
@font-face {  
font-family: yourFontName ;  
src: url( path/to/file/FONTNAME.ttf ) format(&quot;truetype&quot;);  
}
</pre>
<p>Once you've defined your font all you need to do is use it like you would any other standard font family</p>
<pre class="brush: css">
 
.fontclass { font-family: FONTNAME , verdana, helvetica, sans-serif;  
} </pre>
<p>As you may expect, there are a few caveats to using this. Whilst IE does support the font-face element it is only able to use &quot;Embedded OpenType&quot; fonts (eot). Not the end of the world, but you'll just have to convert your TTF to EOT.</p>
<pre class="brush: css">
@font-face {  
  font-family: &quot; CREATED&nbsp;FONTNAME &quot;;  
  src: url( path/to/file/FONTNAME.eot ); /* IE */  
  src: local(&quot; FONTNAME &quot;), url(path/to/file/FontFileName.ttf ) format(&quot;truetype&quot;); /* non-IE */  
} </pre>]]></description>
</item>
<item>
<title><![CDATA[creating a conditional css with php]]></title>
<link>http://www.populate.it/conditional_css_php.html</link>
<guid>http://www.populate.it/conditional_css_php.html</guid>
<description><![CDATA[<p>We had a requirement to do this on a recent site as the design team wanted a lot of very subtle transparency. Ideally we wanted to use PNGs for a lot of this but, with IE6 support for transparent PNG being, well, non-existent we had an issue. We've used PNG-fix in the past but don't particularly like this solution. In this case we wanted to disable certain styles for IE 6 and change some background images on buttons from nicely anti-aliased PNGs to jaggy GIFs. We also added this module as it allows us to detect mobile devices in the style-sheet and apply different styles to the same HTML files.</p>
<p>Its pretty easy to run a conditional in the HTML and link to a completely different style-sheet for certain browsers. I personally don't like this solution as having the same styles in completely separate files is asking for trouble when sooner or later one CSS is updated and the other isn't and the site isn't checked in all browsers. This is especially likely to happen when multiple developers are working on the same files. Far better to have an if-then-else statement wrapped around the style inside the CSS, then its obvious what is happening.</p>
<p>Our requirement here is slightly different to a normal situation here as I could use our template engine to parse the file but the fundamental rules are the same and I've chnaged our code slightly to refect the more typical scenraio.</p>
<h2>Part 1 redirect all of your filename.css requests to a server side script</h2>
<p>I did this with an .htaccess script&nbsp;using:</p>
<pre class="brush: php">
RewriteRule ^([^.]+)$ /css_parser.php [NC,QSA,L]
</pre>
<h2>&nbsp;</h2>
<h2>Part 2 build a script that reads your css file and resolves the conditional statements</h2>
<pre class="brush: php">
// set up an array to hold all of the values 
$visit = array ();
$visit[&quot;userAgent&quot;] = $_SERVER['HTTP_USER_AGENT'];
$visit[&quot;remoteAddr&quot;] = $_SERVER['REMOTE_ADDR'];
$visit[&quot;browser&quot;] = &quot;&quot;;
$visit[&quot;browserVersion&quot;] = 0;

if (preg_match( '/mozilla.*applewebkit/([0-9a-z+-.]+).*mobile.*/si', $visit['userAgent'], $thisUserAgent ))	{ // Safari Mobile
    $visit['browser'] = &quot;SafMob&quot;;
    $visit['browserVersion'] = $thisUserAgent[1];
} elseif (preg_match( '/mozilla.*applewebkit/([0-9a-z+-.]+).*/si', $visit['userAgent'], $thisUserAgent )) { // Webkit (Safari, Shiira etc)
    $visit['browser'] = &quot;Webkit&quot;;
    $visit['browserVersion'] = $thisUserAgent[1];
} elseif ( preg_match( '/mozilla.*opera ([0-9a-z+-.]+).*/si', $visit['userAgent'], $thisUserAgent) || preg_match( '/^opera/([0-9a-z+-.]+).*/si', $visit['userAgent'], $aUserAgent)){ // Opera
    $visit['browser'] = &quot;Opera&quot;;
    $visit['browserVersion'] = $thisUserAgent[1];
} elseif ( preg_match( '/mozilla.*rv:([0-9a-z+-.]+).*gecko.*/si', $visit['userAgent'], $thisUserAgent )) {// Gecko (Firefox, Mozilla, Camino etc)
    $visit['browser'] = &quot;Gecko&quot;;
    $visit['browserVersion'] = $thisUserAgent[1];
} elseif ( preg_match( '/mozilla.*MSIE ([0-9a-z+-.]+).*Mac.*/si', $visit['userAgent'], $thisUserAgent )) { // IE Mac
    $visit['browser'] = &quot;IEMac&quot;;
    $visit['browserVersion'] = $thisUserAgent[1];
} elseif( preg_match( '/PPC.*IEMobile ([0-9a-z+-.]+).*/si', $visit['userAgent'], $thisUserAgent )) { // MS mobile
    $visit['browser'] = &quot;IEMob&quot;;
    $visit['browserVersion'] = &quot;1.0&quot;;
} elseif( preg_match( '/mozilla.*?MSIE ([0-9a-z+-.]+).*/si', $visit['userAgent'], $thisUserAgent )) { // MSIE
    $visit['browser'] = &quot;IE&quot;;
    $visit['browserVersion'] = $thisUserAgent[1];
} elseif( preg_match( '/mozilla.*konqueror/([0-9a-z+-.]+).*/si', $visit['userAgent'], $thisUserAgent )) { // Konqueror
    $visit['browser'] = &quot;Konq&quot;;
    $visit['browserVersion'] = $thisUserAgent[1];
} elseif( preg_match( '/mozilla.*PSP.*; ([0-9a-z+-.]+).*/si', $visit['userAgent'], $thisUserAgent )) {// PSP
    $visit['browser'] = &quot;PSP&quot;;
    $visit['browserVersion'] = $thisUserAgent[1];
} elseif( preg_match( '/mozilla.*NetFront/([0-9a-z+-.]+).*/si', $visit['userAgent'], $thisUserAgent )) {// NetFront
    $visit['browser'] = &quot;NetF&quot;;
    $visit['browserVersion'] = $thisUserAgent[1];
}
</pre>
<h2>&nbsp;</h2>
<h2>Step 3: markup your css file</h2>
<p>Although this is stored as a CSS file we can write normal PHP code into here and then parse it later with an 'eval'.&nbsp;</p>
<pre class="brush: php">
/*stylesheet*/
body {font-family:arial, helvetica, sans-serif}
/*now we are going to wrap a conditional around our link class*/
<?php if ($visit['browser'] =="IE") {?>
    <?php if ($visit['browserVersion'] &lt; 7) {?>
        a.button {position relative; display:block; width 24px; height: 24px; background-image:url(../images/IE6_button.gif)
    <?php } else { ?>
        a.button {position relative; display:block; width 24px; height: 24px; background-image:url(../images/button.png)
    <?php } ?>
<?php } else { ?>
    a.button {position relative; display:block; width 24px; height: 24px; background-image:url(../images/button.png)
<?php } ?>
</pre>
<h2>Part 4: finally we need to evaluate the CSS and return it the visitors browser</h2>
<pre class="brush: php">
$pathToFile = &quot;&quot; // here you will somehow have to get the path to your css file, it might be that you only have one so you can add a static value, it might be that you need to get which file was called by using $_SERVER['REQUEST_URI'] or something..
eval(&quot;$cssContents = &quot;&quot;.file_get_contents($pathToFile).&quot;&quot;;&quot;);</pre>
<p>You now have the parsed css contents in a variable ($cssContents) and you need to send this file back to the users browser.</p>
<pre class="brush: php">
$expires = 60*60*24;&lt;
header('Pragma: public');
header('Expires: Mon, 26 Jul 1997 05:00:00 GMTn');
header('Content-Disposition: inline');
header('Cache-Control: maxage='.$expires');
header('Expires: ' . gmdate('D, d M Y H:i:s', time()+$expires) . ' GMT');
header('Content-type: text/css');

print $cssContents;
exit;
</pre>
<p>&nbsp;</p>
<p>That should be it, as usual any feedback or addtions would be appreciated, if you have a similar article post a link and if we think its relevant will post it here.</p>]]></description>
</item>
<item>
<title><![CDATA[Does google follow javascript onclick events?]]></title>
<link>http://www.populate.it/does-google-follow-onclick.html</link>
<guid>http://www.populate.it/does-google-follow-onclick.html</guid>
<description><![CDATA[<div><strong>The simple answer is yes.</strong></div>
<div>&nbsp;</div>
<div>We always used to use onclick events in links to get the visitor to specific places in our shopping system that we did not want Google to follow. This was a deliberate move to do things like set the number of products shown per section page etc but to stop Google and the other search engines indexing the pages in this way as it would mean multiple versions of the same content being indexed with little or no differences except the querystring and the number of products etc.&nbsp;</div>
<div>&nbsp;</div>
<div>Our shopping system uses a cart that is retrieved by an ID located in a cookie, if the cookie is not established a default cart is used. This cart stores various settings that the shop uses to display the site, currency, language, prices with or without tax, products per section etc as well as the more standard products in cart, and eventually checkout details including customer information. The default cart is used until something is done by the visitor that requires something other than the default cart, logging-in, changing a preference or adding something to the cart. At this point a database entry is created and the reference to it stored in a cookie. This was principally done to avoid the huge number of carts created by a bot visiting the site (they don't accept the cookie so a new cart is created with each page visited)&nbsp;we also have the facility at this point to set a preference of no cookies that when set automatically appends every link within the site with a query string that identifies the cart ID, thus allowing a visitor with a browser not accepting cookies to use the shop (this is potentially hazardous because the last thing we want to happen is for Google to index the pages with the querystring in place as this would mean potentially infinite version of the same content being indexed with only a difference in the query string...)</div>
<div>&nbsp;</div>
<div>I was interested to see why large number of carts were still being created so started storing the user-agent, the user IP and the URL that was called that created the cart and in that way we started to see that Google was indeed following these onclick events.</div>
<div>below is &nbsp;a sample of the records created.</div>
<div>&nbsp;</div>
<div>&nbsp;</div>
<table class="tableCodeSmall">
    <tbody>
        <tr>
            <td>Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)</td>
            <td>productsPerSection=12&amp;productSortOrder=order&amp;productsSortOrder=priceD</td>
        </tr>
        <tr>
            <td>Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)</td>
            <td>productsPerSection=12&amp;productSortOrder=order&amp;productsSortOrder=priceA</td>
        </tr>
        <tr>
            <td>Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)</td>
            <td>productsPerSection=12&amp;productSortOrder=order&amp;productsSortOrder=priceA</td>
        </tr>
        <tr>
            <td>Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)</td>
            <td>productsPerSection=12&amp;productSortOrder=order&amp;productsSortOrder=priceD</td>
        </tr>
        <tr>
            <td>Mozilla/5.0 (Windows; U; Windows NT 5.1; es-ES; rv:1.9.2.3) Gecko/20100401</td>
            <td>productsPerSection=12&amp;productSortOrder=order&amp;productsSortOrder=priceA</td>
        </tr>
        <tr>
            <td>Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)</td>
            <td>productsPerSection=12&amp;productSortOrder=order&amp;productsSortOrder=none</td>
        </tr>
        <tr>
            <td>Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)</td>
            <td>productsPerSection=12&amp;productSortOrder=order&amp;productsSortOrder=none</td>
        </tr>
        <tr>
            <td>Mozilla/5.0 (Windows; U; Windows NT 6.0; en-US) AppleWebKit/534.3 (KHTML, l</td>
            <td>productsPerSection=24&amp;productSortOrder=order</td>
        </tr>
        <tr>
            <td>Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.5; es-ES; rv:1.9.2.10) Gecko/2</td>
            <td>productsPerSection=12&amp;productSortOrder=order&amp;productsSortOrder=priceD</td>
        </tr>
        <tr>
            <td>Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)</td>
            <td>productsPerSection=12&amp;productSortOrder=order&amp;productsSortOrder=none</td>
        </tr>
        <tr>
            <td>Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)</td>
            <td>productsPerSection=12&amp;productSortOrder=order&amp;productsSortOrder=none</td>
        </tr>
        <tr>
            <td>Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; WOW64; Trident/4.0; SLCC</td>
            <td>productsPerSection=12&amp;productSortOrder=order&amp;productsSortOrder=priceA</td>
        </tr>
        <tr>
            <td>Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; WOW64; Trident/4.0; SLCC</td>
            <td>productsPerSection=12&amp;productSortOrder=order</td>
        </tr>
        <tr>
            <td>ia_archiver (+http://www.alexa.com/site/help/webmasters; crawler@alexa.com)</td>
            <td>productsPerSection=80&amp;productSortOrder=order&amp;productsSortOrder=priceD</td>
        </tr>
        <tr>
            <td>ia_archiver (+http://www.alexa.com/site/help/webmasters; crawler@alexa.com)</td>
            <td>productsPerSection=8&amp;productSortOrder=order</td>
        </tr>
        <tr>
            <td>ia_archiver (+http://www.alexa.com/site/help/webmasters; crawler@alexa.com)</td>
            <td>productsPerSection=40&amp;productSortOrder=order&amp;productsSortOrder=priceD</td>
        </tr>
        <tr>
            <td>ia_archiver (+http://www.alexa.com/site/help/webmasters; crawler@alexa.com)</td>
            <td>productsPerSection=24&amp;productSortOrder=order&amp;productsSortOrder=priceA</td>
        </tr>
        <tr>
            <td>Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0; InfoPath.2;</td>
            <td>productsPerSection=12&amp;productSortOrder=order&amp;productsSortOrder=priceD</td>
        </tr>
        <tr>
            <td>Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; Trident/4.0; InfoPath.2;</td>
            <td>productsPerSection=12&amp;productSortOrder=order&amp;productsSortOrder=priceD</td>
        </tr>
        <tr>
            <td>Mozilla/5.0 (Windows; U; Windows NT 5.1; es-ES; rv:1.8.0.12) Gecko/20070508</td>
            <td>productsPerSection=24&amp;productSortOrder=order</td>
        </tr>
        <tr>
            <td>Mozilla/5.0 (Windows; U; Windows NT 5.1; es-ES; rv:1.9.2.10) Gecko/20100914</td>
            <td>productsPerSection=12&amp;productSortOrder=order</td>
        </tr>
        <tr>
            <td>Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)</td>
            <td>productsPerSection=12&amp;productSortOrder=order&amp;productsSortOrder=priceD</td>
        </tr>
        <tr>
            <td>Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)</td>
            <td>productsPerSection=12&amp;productSortOrder=order&amp;productsSortOrder=priceA</td>
        </tr>
        <tr>
            <td>Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)</td>
            <td>productsPerSection=12&amp;productSortOrder=order&amp;productsSortOrder=priceD</td>
        </tr>
        <tr>
            <td>Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)</td>
            <td>productsPerSection=12&amp;productSortOrder=order&amp;productsSortOrder=priceA</td>
        </tr>
        <tr>
            <td>Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)</td>
            <td>productsPerSection=12&amp;productSortOrder=order&amp;productsSortOrder=priceD</td>
        </tr>
        <tr>
            <td>Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)</td>
            <td>productsPerSection=12&amp;productSortOrder=order&amp;productsSortOrder=priceD</td>
        </tr>
        <tr>
            <td>Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)</td>
            <td>productsPerSection=12&amp;productSortOrder=order&amp;productsSortOrder=priceA</td>
        </tr>
        <tr>
            <td>Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)</td>
            <td>productsPerSection=12&amp;productSortOrder=order&amp;productsSortOrder=none</td>
        </tr>
        <tr>
            <td>Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)</td>
            <td>productsPerSection=12&amp;productSortOrder=order&amp;productsSortOrder=priceA</td>
        </tr>
        <tr>
            <td>ia_archiver (+http://www.alexa.com/site/help/webmasters; crawler@alexa.com)</td>
            <td>productsPerSection=80&amp;productSortOrder=order</td>
        </tr>
        <tr>
            <td>ia_archiver (+http://www.alexa.com/site/help/webmasters; crawler@alexa.com)</td>
            <td>productsPerSection=8&amp;productSortOrder=order&amp;productsSortOrder=priceD</td>
        </tr>
    </tbody>
</table>
<div>&nbsp;</div>
<div>We never use links with querystrings in the URL except when they are called by onclick events as having these indexed is not ideal. So by seeing that carts are being created by the Google bot by following URLs that are only available through onclicks. Interestingly so is the Alexa bot, but there is no evidence of Bing, Yahoo etc being able to follow the onclicks..?&nbsp;</div>
<div>&nbsp;</div>
<div>We have dealt with the issue of these pages being indexed by the system setting the pref or adding the product etc and then redirecting to a clean URL stopping the pages being indexed with the query string. In theory Google won't have accepted the cookie so as soon as they are redirected they are back to browsing the site with the default cart.</div>
<div>&nbsp;</div>
<div>We could have run some sort of filter that detected if the user agent was a bot but this seems to be against the guidelines of Google of showing them the same content as a normal visitor.</div>
<div>&nbsp;</div>
<div>I guess the next experiment is whether and how Google is submitting forms, apparently it does submit simple forms, so does that mean its going to get into the checkout and customer areas? these forms might be too complex with the validation that's in place but I would imaging that the form that adds products to the cart (which is usually only requires one select to be set - qty) would be within its capability. I think its also going to be worth trying to work out if Google ever accepts cookies: apparently not but it would render the above redundant... I might have to add a bit of code that counts the pages each cart 'visits' and see if the carts created by Google bot ever get to more that one page which without the cookie, it shouldn't. It might also be worth seeing if Google ever tells us the user agent is something else and re-crawls the site to see if the content is the same we might be able to discover this by looking at the user agents IP and seeing if it occurs with another user agent.&nbsp;</div>
<div>&nbsp;</div>
<div>I would appreciate some feedback by anyone facing similar issues or who has similar questions</div>
<p>&nbsp;</p>]]></description>
</item>
<item>
<title><![CDATA[How to use  z-indexing in CSS]]></title>
<link>http://www.populate.it/z_index_in_css.html</link>
<guid>http://www.populate.it/z_index_in_css.html</guid>
<description><![CDATA[<p>You may find when using CSS positioning that, on occasion, you may end up with layers that overlap. sometime this can be a required element to the design of your layout. But what if you want the first or second layer to be top, not the last one you've positioned? This is when the z-index property comes into play.</p>
<h3>Z-index? What?</h3>
<p>Think of each positioned layer of you design as pieces of paper. You can lay them one on top of the other in whatever order you like... using the z-index of course. The higher the z-index the closer to the top of the &quot;paper pile&quot; it is going to be. you can even use negative numbers to get the positioned element right down to the bottom. Cool huh?</p>
<h3>Umm... examples please</h3>
<p>Right, quite simply you will need to have some css positioned elements. These will HAVE to have the position attribute set. The z-index will work with either relative or absolute positioned elements. For example:</p>
<pre class="brush: css">
#container {
    position:absolute;
    width:100px;
    height:100px;
    z-index:-1;
}
</pre>
<p><br />
This container will position itelf below the previous element. Use a positive number and the element will be above.<br />
Easy Peasy!</p>
<p>&nbsp;</p>]]></description>
</item>
<item>
<title><![CDATA[How to add an HTML Twitter widget to your website]]></title>
<link>http://www.populate.it/old_style_html_twitter_widget.html</link>
<guid>http://www.populate.it/old_style_html_twitter_widget.html</guid>
<description><![CDATA[<p>Since the lovely people at Twitter have decided to hide away their old style HTML widget in favour of the horrible flash ones I thought it would be a good idea to show how to do it!<br />
<br />
Two bits of code are required to do this....</p>
<h3>Step 1 - The widget</h3>
<div class="code">&lt;div id=&quot;twitter_div&quot;&gt;<br />
&lt;h2 class=&quot;sidebar-title&quot;&gt;Twitter Updates&lt;/h2&gt;<br />
&lt;ul id=&quot;twitter_update_list&quot;&gt;&lt;/ul&gt;<br />
&lt;a href=&quot;http://twitter.com/USERNAME&quot; id=&quot;twitter-link&quot; style=&quot;display:block;text-align:right;&quot;&gt;follow me on Twitter&lt;/a&gt;<br />
&lt;/div&gt;</div>
<p><br />
Paste this where you want you're twitter feed to appear, we'll go into styling it later!<br />
*replace USERNAME with your Twitter username</p>
<h3>Step 2 - Javascript</h3>
<div class="code">&lt;script type=&quot;text/javascript&quot; src=&quot;http://twitter.com/javascripts/blogger.js&quot;&gt;&lt;/script&gt;<br />
&lt;script type=&quot;text/javascript&quot; src=&quot;http://twitter.com/statuses/user_timeline/USERNAME.json?callback=twitterCallback2&amp;amp;count=5&quot;&gt;&lt;/script&gt;</div>
<p><br />
Paste this just above the &lt;/body&gt; tag on any page you wish to display the widget.<br />
*replace USERNAME with your Twitter unsername</p>
<h3>Step 3 - Styling</h3>
<p>This is not the most flexible widget to style, but you can have a good go at getting it to look pretty good.</p>
<div class="code">#twitter_update_list { }<br />
#twitter_div { }<br />
ul#twitter_update_list { }<br />
#twitter_update_list li span { }<br />
#twitter_update_list li span a { }<br />
#twitter_update_list li a { }</div>
<p><br />
By adding this to your stylesheet, you can control the looks of the widget. Play about with it and have fun!</p>]]></description>
</item>
<item>
<title><![CDATA[Resizing images with PHP]]></title>
<link>http://www.populate.it/image_resize_php.html</link>
<guid>http://www.populate.it/image_resize_php.html</guid>
<description><![CDATA[<p>I&nbsp;wrote this function a while back that rezies images using the GDlib functionality that is present in most PHP&nbsp;installs</p>
<div class="code">function resizeImage($imageW, $imageH, $imageIn, $imageOut, $method = &quot;fit&quot;, $cropArray=array(), $fillColour=&quot;FFFFFF&quot;) {<br />
&nbsp;&nbsp; &nbsp;//methods =<br />
&nbsp;&nbsp; &nbsp;//fit = the image fits into the size without distortion usually making it smaller than one of the dimensions<br />
&nbsp;&nbsp; &nbsp;//crop = the image is chopped off so that it fits into the box usually resulting in a loss of image in one plane or the other<br />
&nbsp;&nbsp; &nbsp;//scale = the image is distorted and fits the box exactly<br />
&nbsp;&nbsp; &nbsp;//custom is used ic conjuction with the cropper to select a specific area<br />
&nbsp;&nbsp; &nbsp;$lastSlash = strrpos($imageOut, &quot;/&quot;);<br />
&nbsp;&nbsp; &nbsp;if ($lastSlash!==false) {<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;checkDirectoryExists (substr ($imageOut, 0, $lastSlash + 1));<br />
&nbsp;&nbsp; &nbsp;}<br />
&nbsp;&nbsp; &nbsp;$fileType = strtolower (substr($imageIn, strlen($imageIn)-3));<br />
&nbsp;&nbsp; &nbsp;if (($fileType==&quot;gif&quot;||$fileType==&quot;jpg&quot;||$fileType=&quot;png&quot;)&amp;&amp;file_exists ($imageIn)) {<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;$imageSize = @getimagesize($imageIn);<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;if ($imageSize!==false) {<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;list($originalImageW, $originalImageH) = $imageSize;<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;if ($originalImageW!=0&amp;&amp;$originalImageH!=0) {<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;$targetX = 0;<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;$targetY = 0;<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;$sourceX = 0;<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;$sourceY = 0;<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;$targetW = $imageW;<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;$targetH = $imageH;<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;$sourceW = $originalImageW;<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;$sourceH = $originalImageH;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;switch ($method) {<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;case &quot;distort&quot;: // sizes are as they came in<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;break;&nbsp;&nbsp; &nbsp;<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;case &quot;fixedWidth&quot;:<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;$imageH = (int)($imageW * ($sourcwH/$sourceW));<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;if ($imageH&gt;1000) {$imageH = 1000;}<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;break;<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;case &quot;custom&quot;: // used for the image manager<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;if (count($cropArray)!=8) {print &quot;ERROR: wrong image crop parameters&quot;; exit;}<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;list ($targetX, $targetY, $sourceX, $sourceY, $targetW, $targetH, $sourceW, $sourceH) = $cropArray;<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;break;<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;case &quot;fitWithin&quot;: <br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;case &quot;fit&quot;: <br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;if ($sourceW&gt;$targetW||$sourceH&gt;$targetH) {<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;if ($targetW/$targetH &gt; $sourceW/$sourceH) {&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;$imageW = (int)(($targetH / $originalImageH) * $originalImageW);<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;$targetW = $imageW;<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;} else {<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;$imageH = (int)(($targetW / $originalImageW) * $originalImageH);<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;$targetH = $imageH;<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;}<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;} else {<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;$imageW=$sourceW;<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;$imageH=$sourceH;<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;$targetW=$sourceW;<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;$targetH=$sourceH;<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;}<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;break;<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;default: // crop<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;if ($imageW/$imageH &gt; $originalImageW/$originalImageH) {&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;$sourceY = round ((($originalImageH - (($originalImageW / $imageW) * $imageH)) / 2), 0);<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;$sourceH = $originalImageH - ($sourceY * 2);<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;} else {&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;$sourceX = round ((($originalImageW - (($originalImageH / $imageH) * $imageW)) / 2), 0);<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;$sourceW = $originalImageW - ($sourceX * 2);<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;}<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;break;<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;}&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;$image_out = imagecreatetruecolor($imageW, $imageH);<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;$fillColourHandle = imagecolorallocate($image_out, hexdec('0x'.$fillColour{0}.$fillColour{1}), hexdec('0x'.$fillColour{2}.$fillColour{3}), hexdec('0x'.$fillColour{4}.$fillColour{5}));<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;imagefill($image_out, 0, 0, $fillColourHandle);<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;switch ($fileType) {<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;case &quot;gif&quot;:<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;$image_in = imagecreatefromgif($imageIn);<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;imagecopyresampled($image_out, $image_in, $targetX, $targetY, $sourceX, $sourceY, $targetW, $targetH, $sourceW, $sourceH);<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;imagegif($image_out, $imageOut);<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;break;<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;case &quot;jpg&quot;:<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;$image_in = imagecreatefromjpeg($imageIn);<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;imagecopyresampled($image_out, $image_in, $targetX, $targetY, $sourceX, $sourceY, $targetW, $targetH, $sourceW, $sourceH);<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;imagejpeg($image_out, $imageOut, 90);<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;break;<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;case &quot;png&quot;:<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;$image_in = imagecreatefrompng($imageIn);<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;imagecopyresampled($image_out, $image_in, $targetX, $targetY, $sourceX, $sourceY, $targetW, $targetH, $sourceW, $sourceH);<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;imagepng($image_out, $imageOut, 0); // there is another setting that can be used here for filters <br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;break;<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;}<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;return true;<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;}<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;}<br />
&nbsp;&nbsp; &nbsp;}<br />
&nbsp;&nbsp; &nbsp;return false;<br />
}</div>
<p>All you need to do is call the function passing it the parameters in the following order</p>
<p>$imageW = the width in pixels ot the output file<br />
$imageH = the height in pixels of the output file<br />
$imageIn = the path to the source image, this is the internal path not a url<br />
$imageOut = the path to the output image, this is the internal path not a url this will overwrite anything alrady at this location<br />
$method = how should the image be positioned, there are currently four supported methods:</p>
<ul>
    <li>fit = the image is scaled so that it fits within the given sizes.if the image is smaller in both dimensions it is not scaled up.</li>
    <li>crop = the image is chopped off so that it fits into the box usually resulting in a loss of image in one plane or the other</li>
    <li>scale = the image is distorted and fits the box exactly</li>
    <li>custom = an 8 part array with custom specs is passed as the next parameter to precisely control the output. I use this in conjustion with a javascript driven cropper script. the array is in the form:&nbsp;x-coordinate of destination point, y-coordinate of destination point, x-coordinate of source point, y-coordinate of source point, Destination width, Destination height, Source width, Source height,&nbsp;</li>
</ul>
<p>$cropArray = used with the custom method above<br />
$fillColour = used with the custom method above, allowing the background to be set if the specified position of the source image doesn't fully cover the target image.</p>
<p>&nbsp;</p>
<p>&nbsp;</p>]]></description>
</item>
<item>
<title><![CDATA[PHP upload progress bar]]></title>
<link>http://www.populate.it/php_upload_progress.html</link>
<guid>http://www.populate.it/php_upload_progress.html</guid>
<description><![CDATA[<p>Creating am upload progress bar in PHP is far more difficult than you would initially expect. The first probelm is PHP versions before version 5.2 don't provide the required 'hooks' required to make this information available on your webpage. The second problem is making the whole thing work which requires the use of AJAX and a bit of creative thinking to use an iframe as the target of the form so that the javascript ajax routines can continue to run once the form has been submitted.</p>
<h3>Step 1: Make sure your server is set up properly</h3>
<div class="code">&lt;?php phpinfo(); exit; ?&gt;</div>
<p>Put the code above at the top of one of your pages and call that page in a browser. At the very top you should see the installed PHP version. This needs to be greater than 5.2. You then need to make sure that APC (Alternative PHP Cache) is installed and theapc.rfc1867 setting is switched on. If APC is installed the phpinfo screen will have a seperate section called 'apc' and in that section you should see the setting for APC.rfc1867 and whether it is on or not. If any of these things are incorrect you will need to modify the server configuration or like me get the server support staff to do it for you.&nbsp;</p>
<h3>Step 2: Build the form</h3>
<p>The form will look something like this</p>
<div class="code">&lt;?php $uploadKey = date('YmdHis');?&gt;<br />
&lt;div id=&quot;uploadForm&quot;&gt;<br />
&nbsp; &lt;form  name=&quot;uploadForm&quot; id=&quot;uploadForm&quot; action=&quot;/formtarget.php&quot; method=&quot;POST&quot; enctype=&quot;multipart/form-data&quot; target=&quot;uploadIframe&quot;&gt;<br />
&nbsp;&nbsp;&nbsp; &lt;input type=&quot;hidden&quot; name=&quot;APC_UPLOAD_PROGRESS&quot; id=&quot;progress_key&quot; value=&quot;&lt;?php print $uploadKey;?&gt;&quot;/&gt;<br />
&nbsp;&nbsp;&nbsp; &lt;input type=&quot;file&quot; name=&quot;uploadedFile&quot;/&gt;&lt;br /&gt;<br />
&nbsp;&nbsp;&nbsp; &lt;input type=&quot;submit&quot; onclick=&quot;startProgress('&lt;?php print $uploadKey;?&gt;'');&quot; value=&quot;UPLOAD&quot; /&gt;<br />
&nbsp; &lt;/form&gt;<br />
&lt;/div&gt;<br />
&lt;div id=&quot;progressBar&quot;&gt;&lt;/div&gt;<br />
&lt;iframe id=&quot;uploadIframe&quot; name=&quot;uploadIframe&quot; style=&quot;display:none&quot;&gt;&lt;/iframe&gt;</div>
<p>&nbsp;its a fairly standard form except</p>
<ul>
    <li>it submits to an iframe this is necessary so that the javascript (AJAX) can still run on the top level page refreshing the progress bar. When you have processed the form in the catching page in the iframe you'll need to do a javascript comand parent.location.href or similar.</li>
    <li>There is a special hidden form field called '<span class="attribute-value">APC_UPLOAD_PROGRESS' with a unique value. that you then pass to the progress script so that it can identify which file we are getting the server to tell us the progress of. This hidden field has to be before the file type field in the form.<br />
    </span></li>
    <li>There a div that I called progressBar that we will display the progress bar in</li>
    <li>theres an onclick event on the submit button that we will use to start the uploader, we'll get to the javascript bit in a second</li>
</ul>
<h3>Step 3: create the graphics and CSS</h3>
<p>Two basic classes a grey &lt;div&gt; with a red div inside it, we're going to set the the width of the inner one as percentage of the outer using the percentage passed back from the upload script.. I had these in my common CSS&nbsp;file though you could have these in the &lt;head&gt;. I did have some background images in here to make it a bit nicer but have kept it simple for this example.</p>
<div class="code">.progressGrey {<br />
&nbsp;&nbsp;&nbsp; position:relative;<br />
&nbsp;&nbsp;&nbsp; width: 300px;<br />
&nbsp;&nbsp;&nbsp; padding:1px 0px 1px 3px;<br />
&nbsp;&nbsp;&nbsp; background: #ccc;<br />
&nbsp;&nbsp;&nbsp; color: #666;<br />
&nbsp;&nbsp;&nbsp; font-size: 9px;<br />
&nbsp;&nbsp;&nbsp; border:1px solid #000;<br />
&nbsp;&nbsp;&nbsp; overflow:hidden;<br />
&nbsp;&nbsp;&nbsp; white-space:nowrap; <br />
&nbsp;&nbsp;&nbsp; font-weight:bold<br />
}<br />
.progressRed {<br />
&nbsp;&nbsp;&nbsp; position:absolute;<br />
&nbsp;&nbsp;&nbsp; top:0px;<br />
&nbsp;&nbsp;&nbsp; padding:1px 0px 1px 3px;<br />
&nbsp;&nbsp;&nbsp; left:0px;<br />
&nbsp;&nbsp;&nbsp; height: 15px;<br />
&nbsp;&nbsp;&nbsp; background: #f00;<br />
&nbsp;&nbsp;&nbsp; color: #fff;<br />
&nbsp;&nbsp;&nbsp; font-size: 9px;<br />
&nbsp;&nbsp;&nbsp; border-right:1px solid #000;<br />
&nbsp;&nbsp;&nbsp; overflow:hidden;<br />
&nbsp;&nbsp;&nbsp; white-space:nowrap;<br />
&nbsp;&nbsp;&nbsp; font-weight:bold<br />
}</div>
<h3>Step 4: create the PHP script that reports the upload progress</h3>
<div class="code">&lt;?php<br />
&nbsp;&nbsp; $uploadKey=$_GET[&quot;uploadKey&quot;];<br />
&nbsp;&nbsp; $status = false;<br />
&nbsp;&nbsp; $percentage = 0;<br />
&nbsp;&nbsp; $result = &quot;INITIALISING UPLOAD&quot;;<br />
&nbsp;&nbsp; if (function_exists('apc_fetch')) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $status = apc_fetch('upload_'.$uploadKey);<br />
&nbsp;&nbsp; }<br />
&nbsp;&nbsp; if (is_array($status)) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (array_key_exists(&quot;total&quot;, $status)&amp;&amp;array_key_exists(&quot;current&quot;, $status)) {&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp; $percentage = (int)(($status['current'] / $status['total']) * 100);<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp; if ($status['current']&gt;=$status['total']) {<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; $percentage = 100;<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; $result = &quot;UPLOAD COMPLETE&quot;;<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp; } else {<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; $bytes = array('B','KB','MB','GB','TB');<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; foreach($bytes as $val) {<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; if($status[&quot;total&quot;]&nbsp; &gt; 1024){<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; $status[&quot;total&quot;] = $status[&quot;total&quot;] / 1024;<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; $status[&quot;current&quot;] = $status[&quot;current&quot;] / 1024;<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; } else {<br />
&nbsp;&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; break;<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; $result =&nbsp; $percentage.&quot;% (&quot;.round($status[&quot;current&quot;], 2).&quot; &quot;;<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp; $result.= $val.&quot; of &quot;.round($status[&quot;total&quot;], 2).&quot; &quot;.$val.&quot;)&quot;;<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; &nbsp; }<br />
&nbsp;&nbsp; }<br />
&nbsp;&nbsp; header (&quot;content-type: text/xml&quot;);<br />
&nbsp;&nbsp; print &quot;&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&gt;&quot;;<br />
?&gt;<br />
&lt;progress percentage=&quot;&lt;?php print $percentage;?&gt;&quot; result=&quot;&lt;?php print $result;?&gt;&quot;&gt;&lt;/progress&gt;</div>
<p>Hopefully this should be fairly self-explanatory...</p>
<p>I called this script progress.php and kept in the same directory as the php file that calls it. We're going to call it in the next step in an AJAX&nbsp;command passing the unique upload key to it in a querystring /progress.php?uploadKey=xxxxxx This file will check the progress of the upload with the server and return the result back to the AJAX script as an XML file. We'll check for errors as we go and return some generic values in the event of an unexpected result. I'm going to pass only 2 values back to the AJAX script: an integer with the percentage of the progress and a pre formatted message containing a description of the upload.</p>
<h3>step 5:&nbsp;Create the AJAX script to load and report the progress</h3>
<p>This needs to sit in a javascript file, you can either have it inline in the page that holds the form or link to it in an external .js file.</p>
<div class="code">var XMLHttpArray = [<br />
&nbsp;&nbsp;&nbsp; function() {return new XMLHttpRequest()},<br />
&nbsp;&nbsp;&nbsp; function() {return new ActiveXObject(&quot;Msxml2.XMLHTTP&quot;)},<br />
&nbsp;&nbsp;&nbsp; function() {return new ActiveXObject(&quot;Msxml2.XMLHTTP&quot;)},<br />
&nbsp;&nbsp;&nbsp; function() {return new ActiveXObject(&quot;Microsoft.XMLHTTP&quot;)}<br />
];<br />
var theUploadKey = &quot;&quot;;<br />
function createXMLHTTPObject(){<br />
&nbsp;&nbsp;&nbsp; var xmlhttp = false;<br />
&nbsp;&nbsp;&nbsp; for(var i=0; i&lt;XMLHttpArray.length; i++){<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; try{xmlhttp = XMLHttpArray[i]();}<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; catch(e){continue;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; break;<br />
&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; return xmlhttp;<br />
}<br />
function AjaxRequest(url,callback,method){<br />
&nbsp;&nbsp;&nbsp; var req = createXMLHTTPObject();<br />
&nbsp;&nbsp;&nbsp; req.onreadystatechange= function(){<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; if(req.readyState != 4) {return;}<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; if(req.status != 200) {return;}<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; callback(req);<br />
&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; req.open(method,url,true);<br />
&nbsp;&nbsp;&nbsp; req.setRequestHeader('User-Agent', 'My XMLHTTP Agent');<br />
&nbsp;&nbsp;&nbsp; req.send(null);<br />
}<br />
function startProgress(uploadKey) {<br />
&nbsp;&nbsp;&nbsp; theUploadKey = uploadKey;<br />
&nbsp;&nbsp;&nbsp; document.getElementById(&quot;progressBar&quot;).style.display=&quot;block&quot;;<br />
&nbsp;&nbsp;&nbsp; document.getElementById(&quot;progressBar&quot;).innerHTML = &quot;&lt;h3&gt;Upload progress...&lt;/h3&gt;&lt;div class='progressGrey'&gt;&amp;nbsp;&lt;/div&gt;&quot;;<br />
&nbsp;&nbsp;&nbsp; document.getElementById(&quot;uploadForm&quot;).style.display=&quot;none&quot;;<br />
&nbsp;&nbsp;&nbsp; getProgress(uploadKey);<br />
}&nbsp;&nbsp;&nbsp; <br />
<br />
function getProgress(uploadKey){<br />
AjaxRequest(&quot;/progress.php?uploadKey=&quot;+uploadKey,updateProgress,&quot;get&quot;);<br />
}<br />
function updateProgress(req){<br />
&nbsp;&nbsp;&nbsp; var respXML=req.responseXML;<br />
&nbsp;&nbsp;&nbsp; if(!respXML) {<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; return;<br />
&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; var result=respXML.getElementsByTagName('progress')[0].getAttribute('result');<br />
&nbsp;&nbsp;&nbsp; var percentage=respXML.getElementsByTagName('progress')[0].getAttribute('percentage');<br />
&nbsp;&nbsp;&nbsp; if (percentage&gt;0) {<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; document.getElementById(&quot;progressBar&quot;).innerHTML = &quot;&lt;h3&gt;Upload progress...&lt;/h3&gt;&lt;div class='progressGrey'&gt;&quot;+result+&quot;&lt;div class='progressRed' style='width:&quot;+percentage+&quot;%'&gt;&quot;+result+&quot;&lt;/div&gt;&lt;/div&gt;&quot;;<br />
&nbsp;&nbsp;&nbsp; } else {<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; document.getElementById(&quot;progressBar&quot;).innerHTML = &quot;&lt;h3&gt;Upload progress...&lt;/h3&gt;&lt;div class='progressGrey'&gt;&quot;+result+&quot;&lt;/div&gt;&quot;;<br />
&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; if (percentage&lt;100) {<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; var timeoutID = window.setTimeout(&quot;getProgress(theUploadKey)&quot;, 1000);<br />
&nbsp;&nbsp;&nbsp; }<br />
}</div>
<p>&nbsp;</p>]]></description>
</item>
<item>
<title><![CDATA[Building a captcha code with php gdlib]]></title>
<link>http://www.populate.it/captcha_code_php.html</link>
<guid>http://www.populate.it/captcha_code_php.html</guid>
<description><![CDATA[<p>this article is</p>
<a href="http://www.pwdc.co.uk" target="_blank">coming </a>
<p>soon</p>]]></description>
</item>
</channel>
</rss>
