<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Ankur&#039;s PHP and Javascript blog</title>
	<atom:link href="http://www.ankur.com/blog/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.ankur.com/blog</link>
	<description>PHP and javascript blog</description>
	<lastBuildDate>Tue, 10 Nov 2009 14:28:20 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=abc</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Resume HTTP downloads in PHP using cURL or fsockopen</title>
		<link>http://www.ankur.com/blog/106/php/resume-http-downloads-php-curl-fsockopen/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=resume-http-downloads-php-curl-fsockopen</link>
		<comments>http://www.ankur.com/blog/106/php/resume-http-downloads-php-curl-fsockopen/#comments</comments>
		<pubDate>Fri, 06 Nov 2009 17:14:29 +0000</pubDate>
		<dc:creator>Ankur Motreja</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[cURL]]></category>
		<category><![CDATA[HTTP]]></category>

		<guid isPermaLink="false">http://www.ankur.com/blog/?p=106</guid>
		<description><![CDATA[This post describes a method to download a file using a PHP script and resume the download if the previous download was interrupted. The code here could be used while downloading a new version of a PHP application from the application author&#8217;s website. Two implementation examples are provided &#8211; one using cURL and another using [...]


Related posts:<ol><li><a href='http://www.ankur.com/blog/68/php/curl-wrapper-class-cli-php-extension-support/' rel='bookmark' title='Permanent Link: cURL wrapper class with executable and PHP extension support'>cURL wrapper class with executable and PHP extension support</a></li><li><a href='http://www.ankur.com/blog/90/php/domain-whois-query-php/' rel='bookmark' title='Permanent Link: Domain name WHOIS query using PHP'>Domain name WHOIS query using PHP</a></li><li><a href='http://www.ankur.com/blog/83/php/javascript-css-compression-yui-compressor-php-gzip/' rel='bookmark' title='Permanent Link: Javascript and CSS compression using YUI compressor, PHP and gzip'>Javascript and CSS compression using YUI compressor, PHP and gzip</a></li></ol>]]></description>
			<content:encoded><![CDATA[<p>This post describes a method to download a file using a PHP script and resume the download if the previous download was interrupted. The code here could be used while downloading a new version of a PHP application from the application author&#8217;s website. Two implementation examples are provided &#8211; one using cURL and another using fsockopen.</p>
<p><span id="more-106"></span></p>
<h3>Range header of the HTTP protocol</h3>
<p>First, lets start by seeing how the HTTP protocol allows downloads to be resumed. If you don&#8217;t already have PuTTY, get it from <a rel="nofollow" title="PuTTY" rel="nofollow" href="http://www.chiark.greenend.org.uk/~sgtatham/putty/download.html" target="_blank">here</a>. We will use PuTTY to directly connect to a HTTP server, send it some HTTP headers and see the response.</p>
<p>Create a text file with some text in it (at least 20 characters long to make it easier for us to test). Upload it so it is accessible at http://localhost/file.txt . I have used the URL http://localhost/file.txt . Change the settings below according to your URL. Open PuTTY and use the following settings:</p>
<p>Host Name: localhost<br />
Port: 80<br />
Connection Type: Raw<br />
Close window on exit: Never</p>
<p>Click on Open. In the window that shows up, type the following:</p>
<pre class="brush: plain;">
GET /file.txt HTTP/1.1
Host: localhost
Range: bytes=5-
Connection: Close
</pre>
<p>Make sure you hit enter twice after typing the text above. You should see something like the text below if you had used something like &#8220;abcdefghijklmnopqrstuvwxyz&#8221; as the contents of file.txt:</p>
<pre class="brush: plain;">
HTTP/1.1 206 Partial Content
Date: Fri, 06 Nov 2009 16:25:07 GMT
Server: Apache/2.2.12 (Win32) mod_ssl/2.2.12 OpenSSL/0.9.8k
Last-Modified: Fri, 06 Nov 2009 15:56:25 GMT
ETag: &quot;4000000044a82-1a-477b5e2d8093c&quot;
Accept-Ranges: bytes
Content-Length: 21
Content-Range: bytes 5-25/26
Connection: close
Content-Type: text/plain

fghijklmnopqrstuvwxyz
</pre>
<p>You can see that it has returned a few headers followed by the contents of the file starting from the 6th byte. Try it a few more times modifying the Range header (for example, 5-15 to get bytes 6 to 16).</p>
<h3>Using cURL to resume downloads</h3>
<p>Resuming a download using cURL is quite straight forward. We use the CURLOPT_RANGE option to set the range if the file we are trying to download already exists and use the &#8220;a&#8221; option to fopen to append the contents to the file. The code is below:</p>
<pre class="brush: php;">
$url=&quot;http://localhost/file.txt&quot;;
$fileName = &quot;file.txt&quot;;

$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);

if (file_exists($fileName)) {
	$from = filesize($fileName);
	curl_setopt($ch, CURLOPT_RANGE, $from . &quot;-&quot;);
}

$fp = fopen($fileName, &quot;a&quot;);
if (!$fp) {
	exit;
}
curl_setopt($ch, CURLOPT_FILE, $fp);
$result = curl_exec($ch);
curl_close($ch);

fclose($fp);
</pre>
<h3>Using fsockopen to resume downloads</h3>
<p>Resuming a download with fsockopen is more involved as it requires us to send the request headers and then parse the response headers:</p>
<pre class="brush: php;">
$url=&quot;http://localhost/file.txt&quot;;
$fileName = &quot;file.txt&quot;;

$partialContent = false;
$finalFileSize = 0;

$urlParts = parse_url($url);
$socketHandler = fsockopen($urlParts[&quot;host&quot;], 80, $errno, $errstr, 30);
if (!$socketHandler) {
	exit;
} else {
	$from = 0;

	if (file_exists($fileName)) {
		$from = filesize($fileName);
	}

	$out = &quot;GET &quot; . $urlParts[&quot;path&quot;] . &quot; HTTP/1.1\r\n&quot;;
	$out .= &quot;Host: &quot; . $urlParts[&quot;host&quot;] . &quot;\r\n&quot;;
	$out .= &quot;Range: bytes=&quot; . $from . &quot;-\r\n&quot;;
	$out .= &quot;Connection: Close\r\n\r\n&quot;;

	$headerFound = false;

	if (!$fileHandler = fopen($fileName, &quot;a&quot;)) {
		exit;
	}

	fwrite($socketHandler, $out);
	while (!feof($socketHandler)) {
		if ($headerFound) {
			if ($partialContent) {
				$result = fread($socketHandler, 8192);

				if (fwrite($fileHandler, $result) === false) {
					exit;
				}
			} else {
				fclose($fileHandler);
				fclose($socketHandler);
				exit;
			}
		} else {
			$result = fgets($socketHandler, 8192);
			$result = trim($result);
			if ($result === &quot;&quot;) {
				$headerFound = true;
			}

			if (strstr($result, &quot;206 Partial Content&quot;)) {
				$partialContent = true;
			}

			if (preg_match(&quot;/^Content-Range: bytes (\d+)-(\d+)\/(\d+)$/&quot;, $result, $matches)) {
				$finalFileSize = intval($matches[3]);
			}
		}
	}
	fclose($fileHandler);
	fclose($socketHandler);

	clearstatcache();

	if (filesize($fileName) == $finalFileSize) {
		// success
	} else {
		exit;
	}
}
</pre>


<p>Related posts:<ol><li><a href='http://www.ankur.com/blog/68/php/curl-wrapper-class-cli-php-extension-support/' rel='bookmark' title='Permanent Link: cURL wrapper class with executable and PHP extension support'>cURL wrapper class with executable and PHP extension support</a></li><li><a href='http://www.ankur.com/blog/90/php/domain-whois-query-php/' rel='bookmark' title='Permanent Link: Domain name WHOIS query using PHP'>Domain name WHOIS query using PHP</a></li><li><a href='http://www.ankur.com/blog/83/php/javascript-css-compression-yui-compressor-php-gzip/' rel='bookmark' title='Permanent Link: Javascript and CSS compression using YUI compressor, PHP and gzip'>Javascript and CSS compression using YUI compressor, PHP and gzip</a></li></ol></p>]]></content:encoded>
			<wfw:commentRss>http://www.ankur.com/blog/106/php/resume-http-downloads-php-curl-fsockopen/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Relative time in PHP with flexible detail level</title>
		<link>http://www.ankur.com/blog/100/php/relative-time-php-flexible-detail-level/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=relative-time-php-flexible-detail-level</link>
		<comments>http://www.ankur.com/blog/100/php/relative-time-php-flexible-detail-level/#comments</comments>
		<pubDate>Tue, 27 Oct 2009 18:36:10 +0000</pubDate>
		<dc:creator>Ankur Motreja</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[Relaive time]]></category>

		<guid isPermaLink="false">http://www.ankur.com/blog/?p=100</guid>
		<description><![CDATA[This post describes how you can display relative or nicer time values like 10 days, 4 hours and 6 minutes ago instead of a date like 26 October, 2009 6:45 PM. The function is flexible enough to take a parameter for the details level you desire &#8211; for example, in the above example, the detail [...]


No related posts.]]></description>
			<content:encoded><![CDATA[<p>This post describes how you can display relative or nicer time values like 10 days, 4 hours and 6 minutes ago instead of a date like 26 October, 2009 6:45 PM. The function is flexible enough to take a parameter for the details level you desire &#8211; for example, in the above example, the detail level was 3. So, it displays days, hours and minutes. If it was 4, it would have displayed seconds too. If we were using an older date, detail level of 3 might have displayed years, months and weeks.</p>
<p><span id="more-100"></span></p>
<p>Here&#8217;s the code:</p>
<pre class="brush: php;">
/*
 * Takes a unix timestamp and returns a relative time string such as &quot;3 minutes ago&quot;,
 *   &quot;2 months from now&quot;, &quot;1 year ago&quot;, etc
 * The detailLevel parameter indicates the amount of detail. The examples above are
 * with detail level 1. With detail level 2, the output might be like &quot;3 minutes 20
 *   seconds ago&quot;, &quot;2 years 1 month from now&quot;, etc.
 * With detail level 3, the output might be like &quot;5 hours 3 minutes 20 seconds ago&quot;,
 *   &quot;2 years 1 month 2 weeks from now&quot;, etc.
 */
function nicetime($timestamp, $detailLevel = 1) {

	$periods = array(&quot;second&quot;, &quot;minute&quot;, &quot;hour&quot;, &quot;day&quot;, &quot;week&quot;, &quot;month&quot;, &quot;year&quot;, &quot;decade&quot;);
	$lengths = array(&quot;60&quot;, &quot;60&quot;, &quot;24&quot;, &quot;7&quot;, &quot;4.35&quot;, &quot;12&quot;, &quot;10&quot;);

	$now = time();

	// check validity of date
	if(empty($timestamp)) {
		return &quot;Unknown time&quot;;
	}

	// is it future date or past date
	if($now &gt; $timestamp) {
		$difference = $now - $timestamp;
		$tense = &quot;ago&quot;;

	} else {
		$difference = $timestamp - $now;
		$tense = &quot;from now&quot;;
	}

	if ($difference == 0) {
		return &quot;1 second ago&quot;;
	}

	$remainders = array();

	for($j = 0; $j &lt; count($lengths); $j++) {
		$remainders[$j] = floor(fmod($difference, $lengths[$j]));
		$difference = floor($difference / $lengths[$j]);
	}

	$difference = round($difference);

	$remainders[] = $difference;

	$string = &quot;&quot;;

	for ($i = count($remainders) - 1; $i &gt;= 0; $i--) {
		if ($remainders[$i]) {
			$string .= $remainders[$i] . &quot; &quot; . $periods[$i];

			if($remainders[$i] != 1) {
				$string .= &quot;s&quot;;
			}

			$string .= &quot; &quot;;

			$detailLevel--;

			if ($detailLevel &lt;= 0) {
				break;
			}
		}
	}

	return $string . $tense;

}
</pre>
<p>And some examples:</p>
<pre class="brush: php;">
echo nicetime(time());
</pre>
<p>The result would be &#8220;1 second ago&#8221;</p>
<pre class="brush: php;">
echo nicetime(time() - 839283);
</pre>
<p>The result would be &#8220;1 week ago&#8221;</p>
<pre class="brush: php;">
echo nicetime(time() - 8392783);
</pre>
<p>The result would be &#8220;3 months ago&#8221;</p>
<pre class="brush: php;">
echo nicetime(time() - 8392783, 3);
</pre>
<p>The result would be &#8220;3 months 1 week 6 days ago&#8221;</p>
<pre class="brush: php;">
echo nicetime(time() - 83592783, 3);
</pre>
<p>The result would be &#8220;2 years 7 months 2 weeks ago&#8221;</p>
<pre class="brush: php;">
echo nicetime(time() - 83592783, 5);
</pre>
<p>The result would be &#8220;2 years 7 months 2 weeks 1 day 12 hours ago&#8221;</p>
<pre class="brush: php;">
echo nicetime(time() + 90532, 5);
</pre>
<p>The result would be &#8220;1 day 1 hour 8 minutes 52 seconds from now&#8221;</p>


<p>No related posts.</p>]]></content:encoded>
			<wfw:commentRss>http://www.ankur.com/blog/100/php/relative-time-php-flexible-detail-level/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Domain name WHOIS query using PHP</title>
		<link>http://www.ankur.com/blog/90/php/domain-whois-query-php/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=domain-whois-query-php</link>
		<comments>http://www.ankur.com/blog/90/php/domain-whois-query-php/#comments</comments>
		<pubDate>Mon, 26 Oct 2009 18:01:17 +0000</pubDate>
		<dc:creator>Ankur Motreja</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[WHOIS]]></category>

		<guid isPermaLink="false">http://www.ankur.com/blog/?p=90</guid>
		<description><![CDATA[This post is about a PHP class which allows you to check if a domain name is available or not using WHOIS servers. The class simply opens a socket connection to the WHOIS server and passes the domain name to check for. Based on the available string you provide, it checks if the domain name [...]


Related posts:<ol><li><a href='http://www.ankur.com/blog/106/php/resume-http-downloads-php-curl-fsockopen/' rel='bookmark' title='Permanent Link: Resume HTTP downloads in PHP using cURL or fsockopen'>Resume HTTP downloads in PHP using cURL or fsockopen</a></li><li><a href='http://www.ankur.com/blog/68/php/curl-wrapper-class-cli-php-extension-support/' rel='bookmark' title='Permanent Link: cURL wrapper class with executable and PHP extension support'>cURL wrapper class with executable and PHP extension support</a></li></ol>]]></description>
			<content:encoded><![CDATA[<p>This post is about a PHP class which allows you to check if a domain name is available or not using WHOIS servers. The class simply opens a socket connection to the WHOIS server and passes the domain name to check for. Based on the available string you provide, it checks if the domain name is available or not.</p>
<p><span id="more-90"></span> The PHP code is below:</p>
<pre class="brush: php;">
class WhoisQuery {

	var $whoisServer;
	var $availableString;
	var $domainName;
	var $extension;

	function checkAvailability() {

		$output = &quot;&quot;;

		if(($connection = @fsockopen($this-&gt;whoisServer, 43, $errno, $errstr, 15)) == false){
			return array(&quot;errno&quot; =&gt; $errno, &quot;errstr&quot; =&gt; $errstr);
		}

		fputs($connection, $this-&gt;domainName . $this-&gt;extension . &quot;\\r\\n&quot;);

		while(!feof($connection)) {
			$output .= fgets($connection, 4096);
		}

		fclose($connection);

		if (strlen($output) == 0) {
			return array(&quot;errno&quot; =&gt; 0, &quot;errstr&quot; =&gt; &quot;no output&quot;);
		}

		if ( is_integer( strpos($output, $this-&gt;availableString) ) ) {
			return true;
		} else {
			return false;
		}

	}

}
</pre>
<p>You can use it as shown below:</p>
<pre class="brush: php;">
$domainAvailability = new WhoisQuery;
$domainAvailability-&gt;whoisServer = &quot;whois.verisign-grs.com&quot;;
$domainAvailability-&gt;availableString = &quot;No match for&quot;;
$domainAvailability-&gt;domainName = &quot;ankur&quot;;
$domainAvailability-&gt;extension = &quot;.com&quot;;

$result = $domainAvailability-&gt;checkAvailability();

if ($result === true) {
	echo &quot;available&quot;;
} elseif ($result === false) {
	echo &quot;not available&quot;;
} else {
	echo $result[&quot;errstr&quot;];
}
</pre>
<p>We pass it the WHOIS server in whoisServer, the string that should be present in the response if the domain name is available in availableString, the first part of the domain name in domainName and the extension in extension. $result is an array with keys errno and errstr if an error occurred, true if the domain name is available and false if it isn&#8217;t.  Please note that WHOIS servers may limit the frequency of queries you perform. This has not been handled in the class.</p>
<p>You can connect to a WHOIS server manually using a program like <a rel="nofollow" rel="nofollow" href="http://www.chiark.greenend.org.uk/~sgtatham/putty/download.html" target="_blank">PuTTY </a>. Enter the WHOIS server name in the Host Name section and use the port 43. Type in the full domain name (example, ankur.com) and the response will be the WHOIS data.</p>
<p>Now, how do you find WHOIS servers for the extension you would like to check ? whois-servers.net provides some aliases for whois servers. For example, use com.whois-servers.net to connect to the .com WHOIS server. You can also check the <a rel="nofollow" rel="nofollow" href="http://www.iana.org/domains/root/db/" target="_blank">IANA&#8217;s Database of Top Level Domains</a> to see if it contains WHOIS server information for your extension.</p>


<p>Related posts:<ol><li><a href='http://www.ankur.com/blog/106/php/resume-http-downloads-php-curl-fsockopen/' rel='bookmark' title='Permanent Link: Resume HTTP downloads in PHP using cURL or fsockopen'>Resume HTTP downloads in PHP using cURL or fsockopen</a></li><li><a href='http://www.ankur.com/blog/68/php/curl-wrapper-class-cli-php-extension-support/' rel='bookmark' title='Permanent Link: cURL wrapper class with executable and PHP extension support'>cURL wrapper class with executable and PHP extension support</a></li></ol></p>]]></content:encoded>
			<wfw:commentRss>http://www.ankur.com/blog/90/php/domain-whois-query-php/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Javascript and CSS compression using YUI compressor, PHP and gzip</title>
		<link>http://www.ankur.com/blog/83/php/javascript-css-compression-yui-compressor-php-gzip/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=javascript-css-compression-yui-compressor-php-gzip</link>
		<comments>http://www.ankur.com/blog/83/php/javascript-css-compression-yui-compressor-php-gzip/#comments</comments>
		<pubDate>Tue, 20 Oct 2009 11:47:46 +0000</pubDate>
		<dc:creator>Ankur Motreja</dc:creator>
				<category><![CDATA[Javascript]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[YUI compressor]]></category>

		<guid isPermaLink="false">http://www.ankur.com/blog/?p=83</guid>
		<description><![CDATA[It is well known that visitors to your site will not wait for a long time for your page to load. This post will show you how to optimize your pages by reducing the number and size of javascript and CSS files.

Compressing javascript and CSS
The YUI Compressor allows you to easily reduce the size of [...]


Related posts:<ol><li><a href='http://www.ankur.com/blog/106/php/resume-http-downloads-php-curl-fsockopen/' rel='bookmark' title='Permanent Link: Resume HTTP downloads in PHP using cURL or fsockopen'>Resume HTTP downloads in PHP using cURL or fsockopen</a></li><li><a href='http://www.ankur.com/blog/68/php/curl-wrapper-class-cli-php-extension-support/' rel='bookmark' title='Permanent Link: cURL wrapper class with executable and PHP extension support'>cURL wrapper class with executable and PHP extension support</a></li></ol>]]></description>
			<content:encoded><![CDATA[<p>It is well known that visitors to your site will not wait for a long time for your page to load. This post will show you how to optimize your pages by reducing the number and size of javascript and CSS files.</p>
<p><span id="more-83"></span></p>
<h3>Compressing javascript and CSS</h3>
<p>The <a rel="nofollow" rel="nofollow" href="http://developer.yahoo.com/yui/compressor/" target="_blank">YUI Compressor</a> allows you to easily reduce the size of javascript and CSS files by removing comments, extra white spaces, reducing the length of variables where applicable, etc from them. The result is a smaller sized file which works exactly like the original.</p>
<p>Compressing using the YUI Compressor is quite straight forward:</p>
<pre class="brush: bash;">
java -jar &quot;yuicompressor-2.4.2.jar&quot; --type js -o &quot;file.compress.js&quot; &quot;file.js&quot;
java -jar &quot;yuicompressor-2.4.2.jar&quot; --type css -o &quot;file.compress.css&quot; &quot;file.css&quot;
</pre>
<p>Here, file.compress.js and file.compress.css are the compressed output files and file.js and file.css are the input files. These compressed files will work exactly like the original ones. So, you can simple replace the originals with these new compressed files and immediately start seeing faster page load times.</p>
<h3>Combining multiple files into one file</h3>
<p>We have reduced the file sizes in the previous step. However, we might still have multiple javascript and CSS files required to completely load the page. This means the page has to make one HTTP request for each file it requires. Why not combine all the javascript files into one single .js file and all the CSS files into one single .css file ?</p>
<p>You can use any text editor and simple copy paste the contents into one javascript and CSS file. You will then need to modify your page to include these files instead of multiple javascript and CSS files.</p>
<p>Please note that this technique of combining files can end up requiring the user to download a large .js and .css file for each page if each page requires a different set of files. In that case, you might want to use this technique for only the core files that are required on each page or most pages.</p>
<h3>Serve gziped files via PHP</h3>
<p>Now that we have reduced the size and number of files considerably, we can further reduce the size by serving gzip content. If you use mod_gzip on apache, you might already be serving gziped files. However, you might still wish to use this section as compressing content on the fly with gzip might be slower than this technique.</p>
<p>We will first need to gzip the contents of the combined file from the previous step. Lets assume the file was file.js and the gzip compressed file is file.js.gz.</p>
<p>This file needs to be served through a PHP file. You can use the PHP code below to serve this file.</p>
<pre class="brush: php;">
$longExpiryOffset = 315360000;
header ( &quot;Cache-Control: public, max-age=&quot; . $longExpiryOffset );
header ( &quot;Expires: &quot; . gmdate ( &quot;D, d M Y H:i:s&quot;, time () + $longExpiryOffset ) . &quot; GMT&quot; );

header ( &quot;Content-type: text/javascript; charset=utf-8&quot; );

//Check if browser can handle gzip content
if (stripos ( $HTTP_SERVER_VARS [&quot;HTTP_ACCEPT_ENCODING&quot;], &quot;gzip&quot; ) === false) {
 readfile(&quot;file.js&quot;);
} else {
 header(&quot;Content-Encoding: gzip&quot;);
 readfile(&quot;file.js.gz&quot;);
}
</pre>
<p>Similarly, to serve CSS, replace text/javascript with text/css in line 5 and change the file names.</p>
<p>Of course, you will have to modify the HTML in your page to load this PHP script instead of the javascript and css files.</p>
<p>These steps should improve the page load time of your page considerably.</p>


<p>Related posts:<ol><li><a href='http://www.ankur.com/blog/106/php/resume-http-downloads-php-curl-fsockopen/' rel='bookmark' title='Permanent Link: Resume HTTP downloads in PHP using cURL or fsockopen'>Resume HTTP downloads in PHP using cURL or fsockopen</a></li><li><a href='http://www.ankur.com/blog/68/php/curl-wrapper-class-cli-php-extension-support/' rel='bookmark' title='Permanent Link: cURL wrapper class with executable and PHP extension support'>cURL wrapper class with executable and PHP extension support</a></li></ol></p>]]></content:encoded>
			<wfw:commentRss>http://www.ankur.com/blog/83/php/javascript-css-compression-yui-compressor-php-gzip/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>AES wrapper class with pure php and MCrypt extension support</title>
		<link>http://www.ankur.com/blog/76/php/aes-wrapper-class-pure-php-mcrypt-extension-support/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=aes-wrapper-class-pure-php-mcrypt-extension-support</link>
		<comments>http://www.ankur.com/blog/76/php/aes-wrapper-class-pure-php-mcrypt-extension-support/#comments</comments>
		<pubDate>Wed, 14 Oct 2009 16:57:49 +0000</pubDate>
		<dc:creator>Ankur Motreja</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[MCrypt]]></category>

		<guid isPermaLink="false">http://www.ankur.com/blog/?p=76</guid>
		<description><![CDATA[The code below is a wrapper class around the AES-128 implementation at http://www.phpclasses.org/browse/package/3650.html and the MCrypt extension. It use the MCrypt extension if it is enabled and use the pure PHP AES-128 class otherwise.


function hex2bin($hex) {

	return pack ( &#34;H*&#34;, $hex );

}

class Cipher {

	public $password;

	public $plainText;

	public $encryptedText;

	public $iv;

	public $mode;

	const AES_128_ECB = &#34;AES_128_ECB&#34;;

	const AES_128_CBC = &#34;AES_128_CBC&#34;;

	public function [...]


Related posts:<ol><li><a href='http://www.ankur.com/blog/68/php/curl-wrapper-class-cli-php-extension-support/' rel='bookmark' title='Permanent Link: cURL wrapper class with executable and PHP extension support'>cURL wrapper class with executable and PHP extension support</a></li></ol>]]></description>
			<content:encoded><![CDATA[<p>The code below is a wrapper class around the AES-128 implementation at <a rel="nofollow" rel="nofollow" href="http://www.phpclasses.org/browse/package/3650.html">http://www.phpclasses.org/browse/package/3650.html</a> and the MCrypt extension. It use the MCrypt extension if it is enabled and use the pure PHP AES-128 class otherwise.</p>
<p><span id="more-76"></span></p>
<pre class="brush: php; collapse: true; light: false; toolbar: true;">
function hex2bin($hex) {

	return pack ( &quot;H*&quot;, $hex );

}

class Cipher {

	public $password;

	public $plainText;

	public $encryptedText;

	public $iv;

	public $mode;

	const AES_128_ECB = &quot;AES_128_ECB&quot;;

	const AES_128_CBC = &quot;AES_128_CBC&quot;;

	public function __construct() {

		$this-&gt;mode = self::AES_128_ECB;

	}

	public function encrypt($useSuppliedIV = false) {

		if (!$this-&gt;plainText) {
			return &quot;&quot;;
		}

		switch ($this-&gt;mode) {

			case self::AES_128_ECB :
			case self::AES_128_CBC :
				if (strlen($this-&gt;password) &gt; 16) {
					$this-&gt;password = substr($this-&gt;password, 0, 16);
				}
				break;

		}

		if (function_exists ( &quot;mcrypt_module_open&quot; ) &amp;&amp; function_exists ( &quot;mcrypt_create_iv&quot; ) &amp;&amp; function_exists ( &quot;mcrypt_generic_init&quot; ) &amp;&amp; function_exists ( &quot;mcrypt_generic&quot; ) &amp;&amp; function_exists ( &quot;mcrypt_generic_deinit&quot; )) {

			switch ($this-&gt;mode) {

				case self::AES_128_ECB :
					$td = mcrypt_module_open ( 'rijndael-128', '', 'ecb', '' );
					break;

				case self::AES_128_CBC :
					$td = mcrypt_module_open ( 'rijndael-128', '', 'cbc', '' );
					break;

			}

			if ($useSuppliedIV) {
				if (strlen ( $this-&gt;iv ) != mcrypt_enc_get_iv_size ( $td )) {
					return null;
				}
			} else {
				$this-&gt;iv = mcrypt_create_iv ( mcrypt_enc_get_iv_size ( $td ), MCRYPT_RAND );
			}

			mcrypt_generic_init ( $td, $this-&gt;password, $this-&gt;iv );
			$this-&gt;encryptedText = mcrypt_generic ( $td, $this-&gt;plainText );
			mcrypt_generic_deinit ( $td );

		} else {

			$aes = new AES128 ( );
			$key = $aes-&gt;makeKey ( $this-&gt;password );

			$plainTextArray = str_split ( $this-&gt;plainText, 16 );

			$lastIndex = count($plainTextArray) - 1;
			if (strlen($plainTextArray[$lastIndex]) != 16) {

				for ($i = strlen($plainTextArray[$lastIndex]); $i &lt; 16; $i++) {
					$plainTextArray[$lastIndex] .= chr (0);
				}

			}

			$this-&gt;encryptedText = &quot;&quot;;

			if ($useSuppliedIV) {
				if (strlen ( $this-&gt;iv ) != 16) {
					return null;
				}
			} else {
				$this-&gt;iv = &quot;&quot;;
				for ($i = 0; $i &lt; 16; $i++) {
					$this-&gt;iv .= chr (rand(0, 255));
				}
			}

			switch ($this-&gt;mode) {

				case self::AES_128_ECB :

					for($i = 0; $i &lt; count ( $plainTextArray ); $i ++) {
						$this-&gt;encryptedText .= $aes-&gt;blockEncrypt ( $plainTextArray [$i], $key );
					}

					break;

				case self::AES_128_CBC :
					$encryptedTextArray = array();
					for ($i = 0; $i &lt; count ( $plainTextArray ); $i ++) {
						if ($i == 0) {
							$input = $this-&gt;iv ^ $plainTextArray[$i];
						} else {
							$input = $encryptedTextArray[$i - 1] ^ $plainTextArray[$i];
						}

						$encryptedTextArray[$i] = $aes-&gt;blockEncrypt ( $input, $key );
					}

					$this-&gt;encryptedText = join(&quot;&quot;, $encryptedTextArray);

					break;
			}
		}

	}

	public function decrypt() {
		if (!$this-&gt;encryptedText) {
			return &quot;&quot;;
		}

		if (function_exists ( &quot;mcrypt_module_open&quot; ) &amp;&amp; function_exists ( &quot;mcrypt_create_iv&quot; ) &amp;&amp; function_exists ( &quot;mcrypt_enc_get_iv_size&quot; ) &amp;&amp; function_exists ( &quot;mcrypt_generic_init&quot; ) &amp;&amp; function_exists ( &quot;mcrypt_generic&quot; ) &amp;&amp; function_exists ( &quot;mcrypt_generic_deinit&quot; )) {

			switch ($this-&gt;mode) {

				case self::AES_128_ECB :
					$td = mcrypt_module_open ( 'rijndael-128', '', 'ecb', '' );
					$this-&gt;iv = mcrypt_create_iv ( mcrypt_enc_get_iv_size ( $td ), MCRYPT_RAND );
					break;

				case self::AES_128_CBC :
					$td = mcrypt_module_open ( 'rijndael-128', '', 'cbc', '' );
					if (strlen ( $this-&gt;iv ) != mcrypt_enc_get_iv_size ( $td )) {
						return null;
					}
					break;

			}

			mcrypt_generic_init ( $td, $this-&gt;password, $this-&gt;iv );
			$this-&gt;plainText = mdecrypt_generic ( $td, $this-&gt;encryptedText );
			mcrypt_generic_deinit ( $td );

		} else {

			$aes = new AES128 ( );
			$key = $aes-&gt;makeKey ( $this-&gt;password );

			$encryptedTextArray = str_split ( bin2hex ( $this-&gt;encryptedText ), 32 );

			$this-&gt;plainText = &quot;&quot;;

			switch ($this-&gt;mode) {

				case self::AES_128_ECB :
					for($i = 0; $i &lt; count ( $encryptedTextArray ); $i ++) {
						$this-&gt;plainText .= $aes-&gt;blockDecrypt ( hex2bin ( $encryptedTextArray [$i] ), $key );
					}
					break;

				case self::AES_128_CBC :
					if (strlen ( $this-&gt;iv ) != 16) {
						return null;
					}

					$plainTextArray = array();
					for ($i = 0; $i &lt; count ( $encryptedTextArray ); $i ++) {
						$output = $aes-&gt;blockDecrypt ( hex2bin($encryptedTextArray[$i]), $key );

						if ($i == 0) {
							$plainTextArray[$i] = $this-&gt;iv ^ $output;
						} else {
							$plainTextArray[$i] = hex2bin($encryptedTextArray[$i - 1]) ^ $output;
						}

						$this-&gt;plainText = join(&quot;&quot;, $plainTextArray);
					}
					break;

			}

		}

		$this-&gt;plainText = trim ( $this-&gt;plainText );

	}

}
</pre>
<p>Save the code above to cipher.php.  In addition to this, you will need the AES128.php file from <a rel="nofollow" rel="nofollow" href="http://www.phpclasses.org/browse/package/3650.html">http://www.phpclasses.org/browse/package/3650.html</a></p>
<p>Here&#8217;s an example of AES-128 ECB mode encryption:</p>
<pre class="brush: php; collapse: true; light: false; toolbar: true;">
include_once (&quot;AES128.php&quot;);
include_once (&quot;cipher.php&quot;);

$encrypt = new Cipher;
$encrypt-&gt;password = &quot;password&quot;;
$encrypt-&gt;plainText = &quot;this is a very long string that we would like to encrypt using AES128&quot;;
$encrypt-&gt;encrypt();

echo &quot;encrypted: &quot; . bin2hex( $encrypt-&gt;encryptedText ) . &quot;&lt;br&gt;&quot;;

$decrypt = new Cipher;
$decrypt-&gt;password = &quot;password&quot;;
$decrypt-&gt;encryptedText = $encrypt-&gt;encryptedText;
$decrypt-&gt;decrypt();

echo &quot;plain text: &quot; . $decrypt-&gt;plainText;
</pre>
<p>The default mode is ECB. So, we don&#8217;t need to set $encrypt-&gt;mode and $decrypt-&gt;mode to Cipher::AES_128_ECB .</p>
<p>Here&#8217;s an example of AES-128 CBC mode encryption using an initialization vector:</p>
<pre class="brush: php; collapse: true; light: false; toolbar: true;">
include_once (&quot;AES128.php&quot;);
include_once (&quot;cipher.php&quot;);

$encrypt = new Cipher;
$encrypt-&gt;mode = Cipher::AES_128_CBC;
$encrypt-&gt;password = &quot;password&quot;;
$encrypt-&gt;plainText = &quot;this is a very long string that we would like to encrypt using AES128&quot;;
$encrypt-&gt;encrypt();

echo &quot;iv: &quot; . bin2hex( $encrypt-&gt;iv ) . &quot;&lt;br&gt;&quot;;
echo &quot;encrypted: &quot; . bin2hex( $encrypt-&gt;encryptedText ) . &quot;&lt;br&gt;&quot;;

$decrypt = new Cipher;
$decrypt-&gt;mode = Cipher::AES_128_CBC;
$decrypt-&gt;iv = $encrypt-&gt;iv;
$decrypt-&gt;password = &quot;password&quot;;
$decrypt-&gt;encryptedText = $encrypt-&gt;encryptedText;
$decrypt-&gt;decrypt();

echo &quot;plain text: &quot; . $decrypt-&gt;plainText;
</pre>


<p>Related posts:<ol><li><a href='http://www.ankur.com/blog/68/php/curl-wrapper-class-cli-php-extension-support/' rel='bookmark' title='Permanent Link: cURL wrapper class with executable and PHP extension support'>cURL wrapper class with executable and PHP extension support</a></li></ol></p>]]></content:encoded>
			<wfw:commentRss>http://www.ankur.com/blog/76/php/aes-wrapper-class-pure-php-mcrypt-extension-support/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>cURL wrapper class with executable and PHP extension support</title>
		<link>http://www.ankur.com/blog/68/php/curl-wrapper-class-cli-php-extension-support/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=curl-wrapper-class-cli-php-extension-support</link>
		<comments>http://www.ankur.com/blog/68/php/curl-wrapper-class-cli-php-extension-support/#comments</comments>
		<pubDate>Tue, 13 Oct 2009 17:19:19 +0000</pubDate>
		<dc:creator>Ankur Motreja</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[cURL]]></category>

		<guid isPermaLink="false">http://www.ankur.com/blog/?p=68</guid>
		<description><![CDATA[Most cURL wrapper classes I found could handle either the PHP extension or the command line executable version of cURL. I needed a class where I could set one variable and have it switch from using the PHP cURL extension to the cURL executable without having to change the other variable of the class.
The class [...]


Related posts:<ol><li><a href='http://www.ankur.com/blog/76/php/aes-wrapper-class-pure-php-mcrypt-extension-support/' rel='bookmark' title='Permanent Link: AES wrapper class with pure php and MCrypt extension support'>AES wrapper class with pure php and MCrypt extension support</a></li><li><a href='http://www.ankur.com/blog/106/php/resume-http-downloads-php-curl-fsockopen/' rel='bookmark' title='Permanent Link: Resume HTTP downloads in PHP using cURL or fsockopen'>Resume HTTP downloads in PHP using cURL or fsockopen</a></li></ol>]]></description>
			<content:encoded><![CDATA[<p>Most cURL wrapper classes I found could handle either the PHP extension or the command line executable version of cURL. I needed a class where I could set one variable and have it switch from using the PHP cURL extension to the cURL executable without having to change the other variable of the class.</p>
<p><span id="more-68"></span>The class I came up with is below:</p>
<pre class="brush: php; collapse: true; light: false; toolbar: true;">

class Curl {

	// Set to &quot;PHP&quot; or the path to the curl executable (binary)
	var $curlExecutable = &quot;PHP&quot;;

	// URL to request, request type (GET or POST), request parameters as an associative array or null for none
	var $url;
	var $requestType = &quot;GET&quot;;
	var $parameters = null;

	// request headers as an array
	var $requestHeaders = array();

	// certification authority, return data with headers, follow redirects and verify peer if URL is https
	var $cainfo = null;
	var $outputWithHeaders = false;
	var $followLocation = false;
	var $SSLVerifyPeer = true;

	// connect to remote server timeout and timeout to download the entire page
	var $connectTimeout = 30;
	var $timeout = 10800;

	// if there was an error, errorNumber and error is populated. data contains the page downloaded
	var $error = null;
	var $errorNumber = null;
	var $data = null;

	function fetchPage() {

		if ($this-&gt;curlExecutable == &quot;PHP&quot;) {
			$ch = curl_init();

			if ($this-&gt;cainfo) {
				curl_setopt($ch, CURLOPT_CAINFO, $this-&gt;cainfo);
			}

			if ($this-&gt;SSLVerifyPeer) {
				curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, true);
			} else {
				curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
			}

			if ($this-&gt;requestType === &quot;POST&quot;) {
				curl_setopt($ch, CURLOPT_POST, 1);

				if ($this-&gt;parameters) {
					if (is_array($this-&gt;parameters)) {

						$encodedParameters = &quot;&quot;;
						$join = &quot;&quot;;

						foreach ($this-&gt;parameters as $name =&gt; $value) {
							$encodedParameters = $encodedParameters . $join . rawurlencode($name) . &quot;=&quot; . rawurlencode($value);
							$join = &quot;&amp;&quot;;
						}

						curl_setopt($ch, CURLOPT_POSTFIELDS, $encodedParameters);

					} elseif (is_string($this-&gt;parameters)) {

						curl_setopt($ch, CURLOPT_POSTFIELDS, $this-&gt;parameters);

					}
				}

			} else {
				curl_setopt($ch, CURLOPT_POST, 0);

				if ($this-&gt;parameters) {
					$encodedParameters = &quot;&quot;;
					$join = &quot;?&quot;;

					foreach ($this-&gt;parameters as $name =&gt; $value) {
						$encodedParameters = $encodedParameters . $join . rawurlencode($name) . &quot;=&quot; . rawurlencode($value);
						$join = &quot;&amp;&quot;;
					}

					$this-&gt;url = $this-&gt;url . $encodedParameters;
				}

			}

			curl_setopt($ch, CURLOPT_HTTPHEADER, $this-&gt;requestHeaders);

			if ($this-&gt;outputWithHeaders) {
				curl_setopt($ch, CURLOPT_HEADER, 1);
			} else {
				curl_setopt($ch, CURLOPT_HEADER, 0);
			}

			if ($this-&gt;followLocation) {
				curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
			} else {
				curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 0);
			}

			curl_setopt($ch, CURLOPT_URL, $this-&gt;url);
			curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);

			curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, $this-&gt;connectTimeout);
			curl_setopt($ch, CURLOPT_TIMEOUT, $this-&gt;timeout);

			$this-&gt;data = curl_exec($ch);
			$this-&gt;error = curl_error($ch);
			$this-&gt;errorNumber = curl_errno($ch);
			curl_close($ch);

			if ($this-&gt;error) {
				return false;
			} else {
				return true;
			}

		} else {

			$command = $this-&gt;executable;

			$command = $command . &quot; -s -S&quot;;

			$command = $command . &quot; --connect-timeout &quot; . $this-&gt;connectTimeout;
			$command = $command . &quot; --max-time &quot; . $this-&gt;timeout;

			if ($this-&gt;cainfo) {
				$command = $command . &quot; --cacert \&quot;&quot; . $this-&gt;cainfo . &quot;\&quot;&quot;;
			}

			if ($this-&gt;outputWithHeaders) {
				$command = $command . &quot; -i&quot;;
			}

			if ($this-&gt;followLocation) {
				$command = $command . &quot; -L&quot;;
			}

			for ($i = 0; $i &lt; count($this-&gt;requestHeaders); $i++) {
				$command = $command . &quot; -H \&quot;&quot; . $this-&gt;requestHeaders[$i] . &quot;\&quot;&quot;;
			}

			if ($this-&gt;parameters){
				$encodedParameters = &quot;&quot;;
				$join = &quot;&quot;;

				foreach ($this-&gt;parameters as $name =&gt; $value) {
					$encodedParameters = $encodedParameters . $join . rawurlencode($name) . &quot;=&quot; . rawurlencode($value);
					$join = &quot;&amp;&quot;;
				}

				$command = $command . &quot; -d &quot; . escapeshellarg($encodedParameters) . &quot;&quot;;
			}

			if ($this-&gt;requestType === &quot;GET&quot;) {
				$command = $command . &quot; -G&quot;;
			}

			$command = $command . &quot; &quot; . $this-&gt;url;

			$descriptorspec = array(
			0 =&gt; array(&quot;pipe&quot;, &quot;r&quot;),
			1 =&gt; array(&quot;pipe&quot;, &quot;w&quot;),
			2 =&gt; array(&quot;pipe&quot;, &quot;w&quot;)
			);

			$process = proc_open($command, $descriptorspec, $pipes);

			if (is_resource($process)) {

				fclose($pipes[0]);    // close stdin as we are not going to supply any input

				$this-&gt;data = stream_get_contents($pipes[1]);    // read stdout
				$this-&gt;error = stream_get_contents($pipes[2]);    // read stderr

				fclose($pipes[1]);
				fclose($pipes[2]);

				$this-&gt;errorNumber = proc_close($process);

			} else {

				return false;

			}

			if ($this-&gt;errorNumber === 0) {
				return true;
			} else {
				return false;
			}

		}

	}

}
</pre>
<p>The following example fetches http://www.google.com :</p>
<pre class="brush: php; collapse: true; light: false; toolbar: true;">
$request = new Curl;
$request-&gt;curlExecutable = &quot;PHP&quot;;
$request-&gt;followLocation = true;
$request-&gt;url = &quot;http://www.google.com&quot;;
if ( $request-&gt;fetchPage() ) {
	header(&quot;Content-Type:text/plain&quot;);
	echo $request-&gt;data;
} else {
	echo &quot;An error occured: &quot; . $request-&gt;errorNumber . &quot; - &quot; . $request-&gt;error;
}
</pre>
<p>This example fetches a random quote (the ones tou see on the top right of this website):</p>
<pre class="brush: php; collapse: true; light: false; toolbar: true;">
$request = new Curl;
$request-&gt;curlExecutable = &quot;PHP&quot;;
$request-&gt;url = &quot;http://www.ankur.com/quotes.php&quot;;
$request-&gt;requestType = &quot;GET&quot;;
$request-&gt;parameters = array(
	&quot;action&quot; =&gt; &quot;random&quot;
);
if ( $request-&gt;fetchPage() ) {
	header(&quot;Content-Type:text/plain&quot;);
	echo $request-&gt;data;
} else {
	echo &quot;An error occured: &quot; . $request-&gt;errorNumber . &quot; - &quot; . $request-&gt;error;
}
</pre>
<p>Unrelated to the cURL wrapper class, you can try changing the action parameter from random to all to fetch all the quotes.</pre>


<p>Related posts:<ol><li><a href='http://www.ankur.com/blog/76/php/aes-wrapper-class-pure-php-mcrypt-extension-support/' rel='bookmark' title='Permanent Link: AES wrapper class with pure php and MCrypt extension support'>AES wrapper class with pure php and MCrypt extension support</a></li><li><a href='http://www.ankur.com/blog/106/php/resume-http-downloads-php-curl-fsockopen/' rel='bookmark' title='Permanent Link: Resume HTTP downloads in PHP using cURL or fsockopen'>Resume HTTP downloads in PHP using cURL or fsockopen</a></li></ol></p>]]></content:encoded>
			<wfw:commentRss>http://www.ankur.com/blog/68/php/curl-wrapper-class-cli-php-extension-support/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Amazing Tree javascript library</title>
		<link>http://www.ankur.com/blog/63/javascript/amazing-tree-javascript-library/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=amazing-tree-javascript-library</link>
		<comments>http://www.ankur.com/blog/63/javascript/amazing-tree-javascript-library/#comments</comments>
		<pubDate>Mon, 12 Oct 2009 09:18:50 +0000</pubDate>
		<dc:creator>Ankur Motreja</dc:creator>
				<category><![CDATA[Javascript]]></category>
		<category><![CDATA[Amazing Tree]]></category>

		<guid isPermaLink="false">http://www.ankur.com/blog/?p=63</guid>
		<description><![CDATA[Some time back, I required a drag and drop tree implemented in javascript where you could rearrange nodes by dragging them around the tree. I decided to make a post and release it. Its called Amazing Tree. The code is available for download from the projects page.
A few demos of the library in action:
Scroll Demo
Full [...]


Related posts:<ol><li><a href='http://www.ankur.com/blog/30/javascript/frame-glider-javascript-library/' rel='bookmark' title='Permanent Link: Frame Glider javascript library'>Frame Glider javascript library</a></li></ol>]]></description>
			<content:encoded><![CDATA[<p>Some time back, I required a drag and drop tree implemented in javascript where you could rearrange nodes by dragging them around the tree. I decided to make a post and release it. Its called <a href="http://www.ankur.com/blog/amazing-tree/">Amazing Tree</a>. The code is available for download from the <a href="http://www.ankur.com/projects.php#AmazingTree">projects</a> page.</p>
<p><span id="more-63"></span>A few demos of the library in action:</p>
<p><a href="http://www.ankur.com/projects/AmazingTree/demo/demo1.html" target="_blank">Scroll Demo</a></p>
<p><a href="http://www.ankur.com/projects/AmazingTree/demo/demo2.html" target="_blank">Full Demo</a></p>
<p><a href="http://www.ankur.com/projects/AmazingTree/demo/demo3.html" target="_blank">Cone Demo</a></p>
<p>You will find more information and detailed documentation at the <a href="http://www.ankur.com/blog/amazing-tree/">Amazing Tree page</a></p>


<p>Related posts:<ol><li><a href='http://www.ankur.com/blog/30/javascript/frame-glider-javascript-library/' rel='bookmark' title='Permanent Link: Frame Glider javascript library'>Frame Glider javascript library</a></li></ol></p>]]></content:encoded>
			<wfw:commentRss>http://www.ankur.com/blog/63/javascript/amazing-tree-javascript-library/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Frame Glider javascript library</title>
		<link>http://www.ankur.com/blog/30/javascript/frame-glider-javascript-library/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=frame-glider-javascript-library</link>
		<comments>http://www.ankur.com/blog/30/javascript/frame-glider-javascript-library/#comments</comments>
		<pubDate>Sun, 04 Oct 2009 10:14:12 +0000</pubDate>
		<dc:creator>Ankur Motreja</dc:creator>
				<category><![CDATA[Javascript]]></category>
		<category><![CDATA[Frame Glider]]></category>

		<guid isPermaLink="false">http://www.ankur.com/blog/?p=30</guid>
		<description><![CDATA[I had written a javascript library Frame Glider some time back which allows you to drag and drop page elements across frames or iframes within a browser window. The code is now available for download from the projects page.

Some demos are available too:
Simple Demo
Complex Demo
Frame as a droppable
More details including detailed documentation are available at [...]


Related posts:<ol><li><a href='http://www.ankur.com/blog/63/javascript/amazing-tree-javascript-library/' rel='bookmark' title='Permanent Link: Amazing Tree javascript library'>Amazing Tree javascript library</a></li><li><a href='http://www.ankur.com/blog/83/php/javascript-css-compression-yui-compressor-php-gzip/' rel='bookmark' title='Permanent Link: Javascript and CSS compression using YUI compressor, PHP and gzip'>Javascript and CSS compression using YUI compressor, PHP and gzip</a></li></ol>]]></description>
			<content:encoded><![CDATA[<p>I had written a javascript library <a href="http://www.ankur.com/blog/frame-glider/" target="_self">Frame Glider</a> some time back which allows you to drag and drop page elements across frames or iframes within a browser window. The code is now available for download from the <a href="http://www.ankur.com/projects.php#FrameGlider" target="_self">projects</a> page.</p>
<p><span id="more-30"></span></p>
<p>Some demos are available too:</p>
<p><a rel="nofollow" href="../../projects/FrameGlider/demo/simple/a.html" target="_blank">Simple Demo</a></p>
<p><a rel="nofollow" href="../../projects/FrameGlider/demo/complex/a.html" target="_blank">Complex Demo</a></p>
<p><a rel="nofollow" href="../../projects/FrameGlider/demo/frame_drop/a.html" target="_blank">Frame as a droppable</a></p>
<p>More details including detailed documentation are available at the <a href="http://www.ankur.com/blog/frame-glider/" target="_self">Frame Glider page</a></p>


<p>Related posts:<ol><li><a href='http://www.ankur.com/blog/63/javascript/amazing-tree-javascript-library/' rel='bookmark' title='Permanent Link: Amazing Tree javascript library'>Amazing Tree javascript library</a></li><li><a href='http://www.ankur.com/blog/83/php/javascript-css-compression-yui-compressor-php-gzip/' rel='bookmark' title='Permanent Link: Javascript and CSS compression using YUI compressor, PHP and gzip'>Javascript and CSS compression using YUI compressor, PHP and gzip</a></li></ol></p>]]></content:encoded>
			<wfw:commentRss>http://www.ankur.com/blog/30/javascript/frame-glider-javascript-library/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

