<?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>Nettuts+ &#187; Tools &amp; Tips</title>
	<atom:link href="http://net.tutsplus.com/category/tutorials/tools-and-tips/feed/" rel="self" type="application/rss+xml" />
	<link>http://net.tutsplus.com</link>
	<description>Web Development &#38; Design Tutorials</description>
	<lastBuildDate>Fri, 20 Nov 2009 19:56:34 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.8.4</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>How to Create a Mashup by Combining 3 Different APIs</title>
		<link>http://net.tutsplus.com/tutorials/tools-and-tips/how-to-create-a-mashup-by-combining-3-different-apis/</link>
		<comments>http://net.tutsplus.com/tutorials/tools-and-tips/how-to-create-a-mashup-by-combining-3-different-apis/#comments</comments>
		<pubDate>Mon, 13 Oct 2008 10:30:36 +0000</pubDate>
		<dc:creator>Chris Cagle</dc:creator>
				<category><![CDATA[Tools & Tips]]></category>
		<category><![CDATA[api]]></category>
		<category><![CDATA[google maps]]></category>
		<category><![CDATA[mashup]]></category>

		<guid isPermaLink="false">http://nettuts.com/?p=1078</guid>
		<description><![CDATA[<img src="http://nettuts.s3.amazonaws.com/089_mashup/200x200.png" alt="API Mashup" />]]></description>
			<content:encoded><![CDATA[<p>This tutorial will show you how to create a mashup of three different <a href="http://en.wikipedia.org/wiki/API">APIs</a> including integration with Google Maps. This idea came about when I was searching through <a href="http://www.programmableweb.com/apis/directory">ProgrammableWeb&#8217;s API directory</a> for a couple APIs that complimented each other enough that I could use one to provide the other with data. What I came up with will be known as the &#8220;Beer Mashup&#8221;. </p>
<p><span id="more-1078"></span></p>
<div class="tutorial_image">
<a href="http://nettuts.s3.amazonaws.com/089_mashup/DEMO.zip"><br />
<img src="http://nettuts.com/wp-content/themes/nettuts/site_images/button_src_nm.jpg" alt=""></a><br />
<a href="http://www.nettuts.com/demos/07_mashup/DEMO/beermashup2.php" target="_blank"><br />
<img src="http://nettuts.com/wp-content/themes/nettuts/site_images/button_demo_nm.jpg" alt=""></a></div>
<div class="tutorial_image"><img src="http://nettuts.s3.amazonaws.com/089_mashup/images/mainphoto.jpg" alt="" /></div>
<h3>Step 1. API Discovery</h3>
<p>While looking through ProgrammableWeb&#8217;s directory, I found an IP geolocating tool called <a href="http://iploc.mwudka.com/">ipLoc</a>. It simply accepts in an IP address and returns relevant location-specific data on it such as it&#8217;s state, city, country, postal code, etc. </p>
<p>I then found the very cool <a href="http://beermapping.com/">Beer Mapping Project</a>, which has a huge directory of bars and pubs from not only across the US, but <a href="http://beermapping.com/brewery-maps/">many other countries</a> as well. Instantly I noticed that this was a perfect compliment to ipLoc because the <a href="http://beermapping.com/api/">BeerMapping API</a> requires a city (which we can get from the ipLoc API) to return a list of local bars and pubs. </p>
<p>Lastly, I also wanted to integrate <a href="http://maps.google.com/">Google Maps</a> into this mashup to plot out the addresses of the bars and pubs to add a bit of interactivity to the page instead of just displaying each bar in a simple HTML list. </p>
<div class="tutorial_image"><img src="http://nettuts.s3.amazonaws.com/089_mashup/images/apilist.jpg" alt="" /></div>
<h3>Step 2. Variable Initialization</h3>
<p>I usually find it best to start PHP documents off with some of the variables that I want to set globally within the script. Here I add a line that silences PHP warning messages (Google Maps spits out many of these if you happen to try to map an invalid address) and my BeerMashup and Google Maps API keys. We will end up using these API keys when we get to their respective steps below.</p>
<pre name="code" class="php">&lt;?php
	error_reporting(E_ERROR|E_PARSE);  //Silence Errors

//Initialize Variables
	$beer_api = 'YOUR_BEERMAPPING_API_KEY';
	$gmaps_api = 'YOUR_GOOGLEMAPS_API_KEY';</pre>
<h3>Step 3. IP Geolocation Setup</h3>
<p>The ipLoc API allows you to either specify an IP address to get data on, or use the default IP address that the script finds.</p>
<p><b>Default Version:</b> <a href="http://iploc.mwudka.com/iploc/json/">http://iploc.mwudka.com/iploc/json/</a><br />
<b>Static Version (IP address is hardcoded):</b> <a href="http://iploc.mwudka.com/iploc/68.162.155.110/json/">http://iploc.mwudka.com/iploc/68.162.155.110/json/</a></p>
<pre name="code" class="php">//Set Location
	//Visitor IP Address
	$ip = getenv("REMOTE_ADDR");

	//via IPLoc
	$iploc = file_get_contents("http://iploc.mwudka.com/iploc/$ip/json/");  //Format: JSON
	$ipdata = json_decode($iploc, true);</pre>
<p>After a little testing, I realized that the default version of the ipLoc API was finding the location (Scottsdale, AZ, USA) of my hosting provider&#8217;s server rather than my home computer&#8217;s IP location (Pittsburgh, PA, USA). To circumvent this, I decided to use the static IP version of the API (Line 2 above) and passed in the IP address that is detected by the <strong><a href="http://us2.php.net/getenv">getenv</a>(&#8221;REMOTE_ADDR&#8221;)</strong> php variable.</p>
<p>After checking if the data has been successfully returned as a decoded <a href="http://www.json.org/">json</a> formatted string, we need to extract only the specific data we want to pass to the BeerMapping API, which is the <em>city</em> and <em>state</em>. </p>
<pre name="code" class="php">	// Error checking
	if ($ipdata['city']) {
		$city = $ipdata['city'];
		$state = $ipdata['region'];
		$location = $city .", ". $state;
	} else {
		$err = "No location data returned for your IP address: ". $ip; 

	}</pre>
<h3>Step 4. Integrating Google Maps</h3>
<p>This step needs to be done now because the next step will add the location points to Google Maps – and Google Maps has to be initialized before any of that can happen. </p>
<p>To make the Google Maps integration as easy and painless as possible, I&#8217;ve enlisted the help of a great PHP class called <a href="http://www.systemsevendesigns.com/phoogle">Phoogle from System Seven Designs</a>. This class takes care of all the Google Maps API heavy lifting for us while just allowing us to worry about the data. </p>
<p>All we need to do to get this to work is to first include the class file we downloaded: <em>phoogle.php</em>, then set some basic map parameters such as the height, width, zoom level and your Google Maps API key. (<a href="http://code.google.com/apis/maps/">Get one of those here</a>). </p>
<pre name="code" class="php">//Phoogle - GoogleMaps PHP Class
	require_once 'phoogle.php';
	$map = new PhoogleMap();
	$map->setAPIKey($gmaps_api); //Using the variable we set in Step 2
	$map->setHeight(450);
	$map->setWidth(750);
	$map->zoomLevel = 6;
	$map->showType = false;</pre>
<h3>Step 5. BeerMapping API</h3>
<p>Since we have the combined city and state in the variable <strong>$location</strong> from Step 3, we have everything we need to pull data from the BeerMapping API. Of course we also need one of their API keys, which can be requested <a href="http://beermapping.com/api/request_key">here</a> (about a 30 seconds process, start to finish). </p>
<p>A BeerMapping API call looks like this according to their <a href="http://beermapping.com/api/examples/">examples</a>:<br />
<b>Real Example:</b> <a href="http://beermapping.com/webservice/loccity/71515667a86b8ec7f58cd22e3af86f6e/pittsburgh,pa">http://beermapping.com/webservice/loccity/71515667a86b8ec7f58cd22e3af86f6e/pittsburgh,pa</a>
<p>After substituting our variables in for the API Key (Step 2) and Location (Step 3), our BeerMapping API call now looks like this:<br />
<b>Our Example:</b> http://beermapping.com/webservice/loccity/$beer_api/$location</p>
<p>After a little playing around with this API, I found that the location can&#8217;t have any spaces. So the below code first gets rid of the space bewtween the &#8220;city, state&#8221; format. Then it replaces all other spaces within the location with underscores &#8220;_&#8221;.</p>
<pre name="code" class="php">//Format Location for use with API
	$locationF = str_replace(", ", ",", $location); // Remove space before "State"
	$locationF = str_replace(" ", "_", $locationF); // Replace space with underscore in "City" name</pre>
<p>Their data can only be returned in xml format, so we can easily extract the data returned by this call with the <a href="http://us.php.net/simplexml_load_file">simplexml_load_file</a> PHP function.</p>
<pre name="code" class="php">//BeerMapping - Format: XML
	$beerdata = simplexml_load_file ("http://beermapping.com/webservice/loccity/$beer_api/$locationF");</pre>
<div class="tutorial_image"><img src="http://nettuts.s3.amazonaws.com/089_mashup/images/blogdata.gif" alt="" /></div>
<p>As the image shows, we first load the whole file into the variable <b>$beerdata</b>. After checking to see if we returned any results…</p>
<pre name="code" class="php">	// Error checking
	$beererr = $beerdata->location->id; //$beererr will be 0 if there were no locations returned
	if ($beererr == '0') {
		$err = "No breweries were found in ". $location;
	} else {</pre>
<p>…the next step is to cycle through each bar/pub returned in the call, extracting all the data we need to pass into Google Maps (Step 4).  </p>
<pre name="code" class="php">		$breweries = $beerdata->location;
		$barcount = count($breweries); //How Many?

		foreach ($breweries as $brewery) {
			$name = $brewery->name;
			$link = $brewery->reviewlink;
			$street = $brewery->street;
			$city = $brewery->city;
			$state = $brewery->state;
			$zip = $brewery->zip;
			$phone = $brewery->phone;

			//Location Point set for the Google Maps API
			$map->addAddress("$street $city $state $zip", "&lt;a href='$link' title='$name BeerMap'>$name&lt;/a>&lt;br/>$street&lt;br />$city, $state $zip&lt;br />Phone: $phone");
		}
	}
?>
</pre>
<p>Line 1 above sets the structure location of the &#8220;locations&#8221;. Line 2 counts the amount of &#8220;locations&#8221; the API result returned. The remaining lines use a <a href="http://us3.php.net/foreach">foreach loop</a> to cycle though each &#8220;location&#8221; and pull out it&#8217;s address information. Line 14 sets a &#8220;point&#8221; for each brewery on our Google Map.</p>
<h3>Step 6. HTML Generation</h3>
<p>After finishing all the PHP code that we&#8217;ve created, we can now work on displaying it. The first few lines shown below are standard in any HTML document, but after that we get back to using PHP. We first check to see if the variable <strong>$err</strong> is FALSE – which would mean that the <strong>$err</strong> variable is empty, or that we never received an error. If we never got an error, we spit out the Google Map, otherwise we spit out an error message. </p>
<pre name="code" class="php">&lt;html xmlns="http://www.w3.org/1999/xhtml">
&lt;!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
&lt;head>
&lt;meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
&lt;link rel="stylesheet" type="text/css" href="styles.css" />
&lt;title>Bars Near &lt;?php echo $location; ?>&lt;/title>
&lt;/head>
	&lt;body>
	&lt;div class="wrapper">
		&lt;div class="header">
			&lt;img class="logo" src="images/logo.png" alt="The Beer Mashup" />

			&lt;p class="footer">Developed by &lt;a href="http://www.cagintranet.com">Chris Cagle&lt;/a> for &lt;a href="http://www.nettuts.com">NETTUTS&lt;/a>&lt;/p>

			&lt;div class="mapdiv">
				&lt;?php
				if (!$err) {
					echo "&lt;div>";
					$map->printGoogleJS();
					$map->showMap();
					echo "&lt;h3>". $location ." &lt;span>(". $barcount ." Bars)&lt;/span>&lt;/h3>";
				} else {
					echo "&lt;p class=\"error\">&lt;b>". $err ."&lt;/b>&lt;/p>";;
				}
				?>
			&lt;/div>
		&lt;/div>
	&lt;/div>
	&lt;/body>
&lt;/html></pre>
<p>After adding in some text and CSS and you now have a great looking web page that displays all the bars and pubs within the vicinity of the location of whoever is viewing the web page. </p>
<p><a href="http://www.nettuts.com/demos/07_mashup/DEMO/beermashup1.php">View the demo of the page as it stands now</a>. The mashup is working great now, but we have one more improvement that will make all the difference when it comes to UI.</a></p>
<h3>Step 7. Changing the Code to Allow Locations to be Input by the Visitor</h3>
<p>At this point, our page works just fine but there is one small caveat: The visitor can only view bars from his or her current location. What if the visitor wants research bars in a different town rather than the one our IP API returned for him or her? Any visitor would want the ability to specify the location to research in. </p>
<p>To allow this, we will have a simple form that will accept in a city and state from the visitor then reload the page for the given location and skip the ipLoc API call completely. We will insert this code right before our <b>&lt;div class=&#8221;mapdiv&#8221;></b> line in Step 6. </p>
<pre name="code" class="html">&lt;form method="post" id="form" action="beermashup2.php">
	&lt;span>location: (ex. New Orleans, LA)&lt;/span>
	&lt;input type="text" value="" name="loc" id="loc" />&lt;br class="clear" />
	&lt;input type="submit" id="submitted" value="SEARCH" name="submitted" />
&lt;/form></pre>
<div class="tutorial_image"><img src="http://nettuts.s3.amazonaws.com/089_mashup/images/webform.jpg" alt="" /></div>
<p>In order to make this work, we will need to wrap the code we made in the ipLoc step (Step 3) in an if-statement that checks if the form was submitted or not. If the form *was not* submitted (which will happen each time the page is initially loaded), then it will use the ipLoc IP geolocation code. If the form *was* submitted, it will take what the user submitted and set our <strong>$location</strong> variable to that. </p>
<pre name="code" class="php">//Set Location
	if ( isset($_POST['loc']) ) {
		//via user input
		$location = $_POST['loc'];
	} else {
		//Visitor IP Address
		$ip = getenv("REMOTE_ADDR");

		//via IPLoc
		$iploc = file_get_contents("http://iploc.mwudka.com/iploc/$ip/json/");  //Format: JSON
		$ipdata = json_decode($iploc, true);

		// Error checking
		if ($ipdata['city']) {
			$city = $ipdata['city'];
			$state = $ipdata['region'];
			$location = $city .", ". $state;
		} else {
			$err = "No location data returned for your IP address: ". $ip;
		}</pre>
<h3>Step 8. Putting it all Together</h3>
<p><a href="http://www.nettuts.com/demos/07_mashup/DEMO/beermashup2.php">View the demo of the final application.</a></p>
<p>You can view the source code of the final project (which is pretty much just the steps above pushed together) and see how I ended up combining 3 separate APIs into one application. Take a stroll for yourself through the <a href="http://www.programmableweb.com/apis/directory">API directory over at ProgrammableWeb</a> and see what you can come up with on your own. Working with APIs is <a href="http://www.cagintranet.com/voice/">my new obsession</a> because it is exciting to be able to create something new and useful from someone else&#8217;s data. If this tutorial has helped you mashup a couple of APIs, post them here &#8211; I would love to see them.</p>
]]></content:encoded>
			<wfw:commentRss>http://net.tutsplus.com/tutorials/tools-and-tips/how-to-create-a-mashup-by-combining-3-different-apis/feed/</wfw:commentRss>
		<slash:comments>51</slash:comments>
		</item>
		<item>
		<title>Organize Your Team with Collabtive</title>
		<link>http://net.tutsplus.com/tutorials/tools-and-tips/organize-your-team-with-collabtive/</link>
		<comments>http://net.tutsplus.com/tutorials/tools-and-tips/organize-your-team-with-collabtive/#comments</comments>
		<pubDate>Fri, 10 Oct 2008 10:30:03 +0000</pubDate>
		<dc:creator>Thord Hedengren</dc:creator>
				<category><![CDATA[Tools & Tips]]></category>
		<category><![CDATA[collabtive]]></category>

		<guid isPermaLink="false">http://nettuts.com/?p=1072</guid>
		<description><![CDATA[<img src="http://nettuts.s3.amazonaws.com/088_Collabtive/200x200.png" alt="Collabtive" />]]></description>
			<content:encoded><![CDATA[<p>
When you&#8217;re managing larger teams of writers, developers, artist, or whatever really, a collaboration software can come in handy. The most popular and most talked about in the blogosphere is without a doubt <a href="http://www.basecamphq.com/">Basecamp</a>, which is a hosted solution that will set you back $$ monthly. If you want to save in on that, or if you just want to have full control of your inside stuff, then open source solution <a href="http://collabtive.o-dyn.de/">Collabtive</a> is for you.
</p>
<p><span id="more-1072"></span></p>
<blockquote><p>
&#8220;Collabtive is collaborative software to get your projects done!&#8221;
</p></blockquote>
<h3>Step 1: Download and Install</h3>
<p>Collabtive is still in beta, the current version is 0.4.8, but so far I&#8217;m very impressed. It is easy to use, and the install was simple enough.</p>
<p>First of all, <a href="http://collabtive.o-dyn.de/">download Collabtive from the website</a>, and upload it to your server. I installed this for my company, and I&#8217;ll use that URL for the examples below. You&#8217;ll need PHP5, by the way, but if you don&#8217;t have that you really should be giving your host a hard time! Anyway, upload the files, and make the following writeable by the server:</p>
<ul>
<li>the <em>/templates_c</em> folder</li>
<li>the <em>/files</em> folder</li>
<li>the file <em>/config/standard/config.php</em></li>
</ul>
<p>Then create a MySQL database for your install, keep the database name, user name, and password nearby, and point your browser to where you uploaded the files, for me that was http://team.cylinderlabs.net. You want to open the install.php file, so that would be http://team.cylinderlabs.net/install.php</p>
<div class="tutorial_image"><img src="http://nettuts.s3.amazonaws.com/088_Collabtive/install1.jpg" border="0" /></div>
<p>From here on it&#8217;s easy. Just fill out the database details (you should probably keep &#8220;localhost&#8221;, which is filled out on beforehand, unless your database is on its own server) and click the Continue button.</p>
<div class="tutorial_image"><img src="http://nettuts.s3.amazonaws.com/088_Collabtive/install2.jpg" border="0" /></div>
<p>Now, fill out the details for the admin account. You don&#8217;t want to loose these, so make sure you remember them. Here you can also import content from Basecamp, should you be a switcher, although this is a feature I haven&#8217;t been able to try since I haven&#8217;t used the service in a long time. Did you try it? Do share your experience in the comments!</p>
<p>Anyway, click Continue when you&#8217;re done.</p>
<div class="tutorial_image"><img src="http://nettuts.s3.amazonaws.com/088_Collabtive/install3.jpg" border="0" /></div>
<p>And you know what, you&#8217;re done! Login, and you&#8217;ll arrive at the Dashboard, looking more or less like the one above. Now, let&#8217;s take this baby for a spin, shall we?</p>
<p>But wait! There&#8217;s one more thing, not mentioned in any readme file. Change the writing permissions of <em>/config/standard/config.php</em> back to read only. You don&#8217;t want people to dig out your database details, now do you? If you&#8217;re really anal about security, you might want to fiddle with the other write settings as well.</p>
<p>Now we&#8217;re done.</p>
<h3>Step 2: Putting Collabtive to Good Use</h3>
<p>The first thing I did was to go to Administration, using the four icons in the top right, and then choose System administration. Here you can change the name of your Collabtive install, the timezone, pick a template (just one included, I&#8217;m afraid), import from Basecamp yet again, and so on.</p>
<div class="tutorial_image"><img src="http://nettuts.s3.amazonaws.com/088_Collabtive/admin.jpg" border="0" /></div>
<p>I then went to the user administration, again, using Administration in the top right and then User administration. Adding a user is simple and straight forward, but if you want a pretty user profile page like me, you&#8217;ll have to urge your users to click the edit button. It looks really bland and boring otherwise. I like the option to download a VCF card for each user, based on the details submitted, by the way. Very corporate-ish.</p>
<div class="tutorial_image"><img src="http://nettuts.s3.amazonaws.com/088_Collabtive/user.jpg" border="0" /></div>
<p>Since this is a collaborative software, you&#8217;ll work a lot with projects and tasks. The first thing you need to do is to create a new project. You do that in Administration, yet again, and then Project administration, where you&#8217;ll find a list of your current projects, and also an Add project button. I added a project for my Notes Blog WordPress theme, mostly to try stuff out, but also to keep track of the time spent on things.</p>
<div class="tutorial_image"><img src="http://nettuts.s3.amazonaws.com/088_Collabtive/project.jpg" border="0" /></div>
<p>Every task belongs to a task list, and that in turn belongs to a milestone, so your next step would be to add a suitable milestone. For me, that&#8217;s an alpha version of the theme. Then you add the task list associated with the milestone, and populate it with tasks. It is all very straight forward, and you can of course appoint everything to different persons working in the system.</p>
<div class="tutorial_image"><img src="http://nettuts.s3.amazonaws.com/088_Collabtive/task.jpg" border="0" /></div>
<p>If you&#8217;ve ever used Basecamp you probably recognize the work flow. While Collabtive is simple compared to Basecamp, at least so far, it does the basics very well. We&#8217;ll be running it in my company for now.</p>
<h3>Step 3: Cool Little Things</h3>
<p>There are some cool little things that I&#8217;d like to point out with Collabtive, the first being every date field in the system. When you click the field, a calendar just pops up, and when you&#8217;ve picked the date, it disappears. No icons or nonsense like that, just a simple and obvious functionality that I like.</p>
<p>Speaking of icons, here and there you&#8217;ll see a disk icon. Hover it to get further options for saving down the associated data, which could be your task list or whatever. Most stuff can be saved as an Excel or PDF file, which is cool. Sure, they could just have had small icons for each of these, but the hover functionality decreases clutter, even though it encumbers the functionality somewhat. Since this is something I won&#8217;t use on a daily basis, I think it is good as it is.</p>
<p>Another cool thing is the online list in the sidebar. If you&#8217;re online at the same time as another user, you can start at chat right then and there with him or her, just by clicking a speech bubble icon to the right of the username.</p>
<div class="tutorial_image"><img src="http://nettuts.s3.amazonaws.com/088_Collabtive/chat.jpg" border="0" /></div>
<p>The Timetracker feature could prove useful as well, you access it on the various project dashboards, where you can easily add a time report for when you worked on the project. This is certainly a good thing, but as always it depends on you remembering to fill out the time tracker form each time, and to add even smaller edits to a project, otherwise it won&#8217;t be a truthful time report in the end. Still, easy to use and manage.</p>
<div class="tutorial_image"><img src="http://nettuts.s3.amazonaws.com/088_Collabtive/timetracker.jpg" border="0" /></div>
<p>There is support for themes, and if you visit <a href="http://collabtive.o-dyn.de/forum/">the Collabtive forums</a>, you&#8217;ll find a few threads about it, but at this time the standard theme is the one you&#8217;ll build upon. Also, there&#8217;s no documentation on this, so that&#8217;s a limitation of course. That being said, just building from the standard theme should make it fairly easy to do some minor edits to fit your need, should you want to brand your install a little harder.</p>
<h3>Wrapping It Up</h3>
<p>I&#8217;m impressed by Collabtive so far. There are a few things I think it lacks, one being a choice of themes to style it. This, along with more localization files, is probably just a matter of time, since the system overall is responsive and easy to use, a true option to Basecamp for smaller organizations.</p>
<p>One thing it has to sort out, however, is a backup functionality. I want it to e-mail me database backups, and perhaps even do backups of uploaded files, so that I can restore my collaborative system should the server end up dying on me. Hopefully this is due in an upcoming version.</p>
<p><a href="http://collabtive.o-dyn.de/">Give Collabtive a go</a> if you need to manage your team, it&#8217;s worth a shot! Also, don&#8217;t forget to let us know how the Basecamp import feature works out for you.</p>
]]></content:encoded>
			<wfw:commentRss>http://net.tutsplus.com/tutorials/tools-and-tips/organize-your-team-with-collabtive/feed/</wfw:commentRss>
		<slash:comments>56</slash:comments>
		</item>
		<item>
		<title>The Best Ways to Fight Spam</title>
		<link>http://net.tutsplus.com/tutorials/tools-and-tips/the-best-ways-to-fight-spam/</link>
		<comments>http://net.tutsplus.com/tutorials/tools-and-tips/the-best-ways-to-fight-spam/#comments</comments>
		<pubDate>Mon, 06 Oct 2008 10:30:32 +0000</pubDate>
		<dc:creator>Justin Shreve</dc:creator>
				<category><![CDATA[Tools & Tips]]></category>
		<category><![CDATA[fight spam]]></category>
		<category><![CDATA[Wordpress]]></category>

		<guid isPermaLink="false">http://nettuts.com/?p=1064</guid>
		<description><![CDATA[<img src="http://nettuts.s3.amazonaws.com/086_FightingSpam/200x200.png" alt="Fighting Spam" />]]></description>
			<content:encoded><![CDATA[<p>
<strong>Spam is one of the major pitfalls of the social web.</strong> According to sites such as <a href="http://www.postini.com/index.php">Postini</a>, 10 out of 12 email messages are spam. As if that weren&#8217;t already enough to make you cringe, 1 in 39 emails contain a virus. Spam is penetrating into other regions of the Internet as well. The creators of the blogging software Wordpress report that nearly <a href="http://akismet.com/stats/">87% of all blog comments are also spam</a>. As messaging and communication applications proliferate throughout the web, developers and site owners have to get creative in the fight against the thousands upon thousands of unwanted messages streaming in every day. Deciding on the best method of spam prevention on your blogs, forums, or even contact forms can be difficult.  In this article we will take a look at a service called Akismet and how it can help. We will also look at why some other methods of fighting spam fail.
</p>
<p><span id="more-1064"></span></p>
<h3>Methods of Fighting Spam</h3>
<p><strong>Disallowing multiple consecutive submissions</strong>. Spammers almost always post more than one SPAM comment or message at a time.  A common method for fighting spam is to log the incoming message with the user&#8217;s IP address and a timestamp of the post. Then, when a user attempts to post multiple comments, you can check to see if the user has posted more than once within a specified window of time, for example 30 seconds, or if the current poster was also the last poster. This is not a bulletproof method because spammers can use proxies when they want to post multiple times, and robots have as much time in the world as they want to  spam your site.</p>
<p>
<div class="tutorial_image"><img src="http://nettuts.s3.amazonaws.com/086_FightingSpam/postingtooquickly.jpg" alt="" border="0" /></div>
</p>
<p><strong>Keyword Blacklist</strong>. Another method of fighting spam is to build a blacklist of common spam keywords yourself and to disallow posts that contain the words. In its most simplest form, you can create an array of keywords and check to see if an incoming string contains them. Spammers have evolved defenses against this method by posting variations of the words. They replace letters with numbers, symbols, and other such characters to create a broad selection of keyword variations.</p>
<p><strong>CAPTCHA</strong>. CAPTCHA (Completely Automated Public Turing Test) is one of the most common spam prevention techniques on the web today.  The technique is very useful, and almost any site that allows you to register for an account or post information publicly uses CAPTCHA in one way or another. CAPTCHA tests can be audio files, but are more commonly images presenting a series of characters and numbers that you have to enter into a form. The technique is a useful tool for blocking robots that attempt to visit your site to post spam messages or create fake accounts with fake information.</p>
<p>CAPTCHA works well for its intended use, but there are minor drawbacks. A CAPTCHA requires (yet another) field for users to fill in after entering usernames, passwords, and security questions. There is understandably an annoyance factor accompanying their use.  In addition, disabled users may not be able to use the CAPTCHA field. Finally, human spammers can also still spam your site because a CAPTCHA only blocks out robot spammers.</p>
<p>
<div class="tutorial_image"><img src="http://nettuts.s3.amazonaws.com/086_FightingSpam/captcha.jpg" alt="" border="0" /></div>
</p>
<h3>So What&#8217;s Left?</h3>
<p>Having reviewed some of the current methods and their weak points, you may be wondering what else we can do to protect our blogging applications.  I would like to introduce a new spam fighting tool from the creators of WordPress. The service is called <a href="http://akismet.com/">Akismet</a> and is described by its creators as a &#8220;&#8230; collaborative effort to make comment and trackback spam a non-issue and restore innocence to blogging, so you never have to worry about spam again.&#8221;</p>
<p>The tool can be implemented in any project as long as you have an API key, which can be used free for non-commercial use or purchased for commercial use for as little as $5 a month. There are several Akismet plugins for existing software, and these are identified later in this article. Alternatively, you can include the service in your own projects as we will demonstrate.</p>
<p>
<div class="tutorial_image"><img src="http://nettuts.s3.amazonaws.com/086_FightingSpam/akismet.jpg" alt="" border="0" /></div>
</p>
<h3>Implementing Akismet in your Own Projects</h3>
<p>As of now the only way to receive an API key is to sign up for a free WordPress.com user account. Turn your browsers towards <a href="http://wordpress.com/signup/">http://wordpress.com/signup/</a> and fill out the normal required fields: username, password, and email as seen below and then read and agree to the <a href="http://wordpress.com/tos/">terms of service</a> agreement. Make sure that you register for a blog as you can not receive an API key without the registration. Don&#8217;t worry about this detail, because the API key won&#8217;t be tied to a specific blog. Once you have finished the registration process you should receive an email with your new API key.</p>
<p>
<div class="tutorial_image"><img src="http://nettuts.s3.amazonaws.com/086_FightingSpam/wordpresssignup.jpg" alt="" border="0" /></div>
</p>
<p>You will now need to download and unzip <a href="http://www.achingbrain.net/files/PHP5Akismet/PHP5Akismet.0.4.zip">PHP5Akismet.0.4.zip</a> (24K) from <a href="http://www.achingbrain.net">Achingbrain</a>. Upload the single php file to an area accessible by your scripts. The other files and documentation are just for reference.</p>
<p>We will assume that you are working with an existing project. This could be anything that allows user contributions such as a forum or blog. We will also assume that the logic for creating and displaying content already exists. With that in mind, our first step is to load the file into our own project.</p>
<pre name="code" class="php">
include "path/to/file/Akismet.class.php";
</pre>
<p>Next we will need to create a new instance of the Akismet class. Using the classes constructor, we can pass our API key and the URL of the site using it. Make sure to replace the following data with your own.</p>
<pre name="code" class="php">
$akismet = new Akismet( "http://myblog.com", "API KEY HERE");
</pre>
<p>
Now the service needs the actual comment data that we want to check. In the following instance I am using some example data, but in production the comment information would derive from POST data. The Akismet service will then compare the comment information to a database of more than 7,486,928,953 spam comments and return a result if the submitted post has been identified as a spam comment.
</p>
<pre name="code" class="php">
$akismet->setCommentAuthor("Justin Shreve");
$akismet->setCommentAuthorEmail("test@test.com");
$akismet->setCommentAuthorURL("http://serenelabs.com");
$akismet->setCommentType("forums");
$akismet->setCommentContent("I really agree with what  you are saying! I can't believe I never thought of that before!");
</pre>
<p>The functions presented here are quite straightforward. The only function that requires some further explanation is the setCommentType function. This is used by Akismet to help the service identify the origin of the comment (was it posted on a public newsgroup, forum, or blog?), and you can pass any argument you want. For example, if you are using the function to spam-proof a wiki, then use wiki as the type. If you are protecting a blog, then use a blog type.</p>
<p>Now we will use a function called isCommentSpam. This is the function that actually contacts the service. The boolean function will return true if the comment is identified as spam and false if the comment is verified as legitimate.</p>
<pre name="code" class="php">
if( $akismet->isCommentSpam() )
{
	// Here we can store logic to deal with spam comments.
	// Usually we can store the comment internally for later reference just in case the service makes a mistake.
}
else
{
	// This is where you would insert the content into the database.
}
</pre>
<p>Using Akismet is as simple as these few lines of code! You have now integrated a spam-fighting service into your site. The service can be used in conjunction with the other forms of spam defense mentioned earlier. Keep in mind that Akismet is a service that grows each time you use it because the functions contribute your spam content to the database. There may be valid messages sometimes identified as spam and vice-versa. As a result, we may want to integrate a little more functionality to deal with potential misidentification.</p>
<p>If a message is wrongly identified as SPAM, then you can notify Akismet, and they will deal with it accordingly. Alternatively, you can mark a comment as SPAM if it happened to fall through the Akismet filter. When implementing the following functionality, make sure that the comment data in the variables is set in the same format as above.</p>
<p>The function</p>
<pre name="code" class="php">
$akismet->submitHam();
</pre>
<p>can be used to notify the service that the comment they reported as spam is actually ok. </p>
<p>While the function</p>
<pre name="code" class="php">
$akismet->submitSpam();
</pre>
<p>can be used to notify the service that a comment that was approved actually is a piece of spam.</p>
<h3>Other Libraries</h3>
<p>PHP5 isn&#8217;t for everyone. Akismet libraries have also been created in a slew of other languages. Below are a few of the most popular:</p>
<ul>
<li><a href="http://kemayo.wordpress.com/2005/12/02/akismet-py/">Python</a></li>
<li><a href="http://miphp.net/blog/view/php4_akismet_class">PHP4</a></li>
<li><a href="http://rubyforge.org/projects/ror-akismet/">Ruby on Rails</a></li>
<li><a href="http://www.codeplex.com/Wiki/View.aspx?ProjectName=AkismetApi">.NET 2.0</a></li>
</ul>
<p>All of these can be easily integrated into your projects in much the same way as described above.</p>
<h3>Popular implementations</h3>
<p>Don&#8217;t feel the need to roll your own software but still want to take use of Akismet? Many solutions already exist for blog, CMS, or forum software:</p>
<ul>
<li><a href="http://resources.invisionpower.com/index.php?appcomponent=downloads&#038;showfile=876">Invision Power Board</a></li>
<li><a href="http://www.eadz.co.nz/blog/article/phpbb-akismet.htm">phpBB</a></li>
<li><a href="http://drupal.org/project/akismet">Drupal</a></li>
<li><a href="http://www.vbulletin.org/forum/showthread.php?t=118421">vBulletin</a></li>
<li><a href="http://loweblog.com/freelance/article/akismet-for-expression-engine/">Expression Engine</a></li>
<li>and of course WordPress by default!</li>
</ul>
<h3>Closing</h3>
<p>I hope that this guide will serve as an introduction into some alternative forms of spam combat.  A site without SPAM not only appears more professional to users, but is also much easier to manage for administrators and moderators.</p>
]]></content:encoded>
			<wfw:commentRss>http://net.tutsplus.com/tutorials/tools-and-tips/the-best-ways-to-fight-spam/feed/</wfw:commentRss>
		<slash:comments>43</slash:comments>
		</item>
		<item>
		<title>Introduction to Adobe Air</title>
		<link>http://net.tutsplus.com/tutorials/tools-and-tips/introduction-to-adobe-air/</link>
		<comments>http://net.tutsplus.com/tutorials/tools-and-tips/introduction-to-adobe-air/#comments</comments>
		<pubDate>Thu, 02 Oct 2008 10:30:21 +0000</pubDate>
		<dc:creator>Cesare Rocchi</dc:creator>
				<category><![CDATA[Tools & Tips]]></category>
		<category><![CDATA[adobe]]></category>
		<category><![CDATA[adobe air]]></category>

		<guid isPermaLink="false">http://nettuts.com/?p=986</guid>
		<description><![CDATA[<img src="http://nettuts.s3.amazonaws.com/083_adobeAirIntro/200x200.png" alt="Adobe Air Intro" />]]></description>
			<content:encoded><![CDATA[<p>This tutorial will introduce you to Adobe Air, a framework to build rich internet applications. This first introduction will show how to create a simple application using Html/Js technologies.<span id="more-986"></span>
</p>
<p><!--more--></p>
<h3>What is Adobe Air?</h3>
<p>Adobe Air is a framework which allows building desktop applications.<br />
	Adobe Air applications are based on two technologies: Html/Js and Flash.<br />
	Developers can choose to build desktop application via Html/Js, Flash or Flex. After a brief overview of the architecture, we will build a simple application using Html/Js.
</p>
<h3>Step 1 &#8211; Architecture of an Air application</h3>
<p>
An Air application is executed by means of a runtime component, which executes the code contained in the air file. As you can see in the figure Adobe provides the runtime component for the three mayor operative systems, Mac OS X, Windows (XP/Vista) and Linux (note: the Linux version is still in beta). The figure might lead to think that the two approaches are exclusive, either you develop in HTML/JS or Flash. Since the air runtime allows &#8220;bridging&#8221; between Javascript and ActionScript engines, you can call javascript code from an swf, manipulate HTML/DOM via ActionScript, etc.
</p>
<div class="tutorial_image"><img src="http://nettuts.s3.amazonaws.com/083_adobeAirIntro/images/architecture.gif" border="0" /></div>
<h3>Step 2 &#8211; OS level functionalities</h3>
<p>Adobe Air runtime is not simply an integration of HTML/JS and Flash technologies. The runtime provides a set of API which allows air applications to interact with OS functionalities like:</p>
<ul>
<li/> File read and write
<li/> Native Windows/Menus creation and management
<li/> Retrieval of internet resources
	</ul>
<p>
Adobe Air includes also SQLite, a database engine to locally store and retrieve data.
</p>
<h3>Step 3 &#8211; Installation</h3>
<p>
To repeat the steps described below you need to install the runtime and the sdk (Software Development Kit), which enables you to build air applications.<br/><br />
The runtime can be downloaded from <a href="http://www.adobe.com/go/getair">http://www.adobe.com/go/getair</a>. Just run the installer and follow the instructions.<br />
The SDK can be downloaded from: <a href="http://www.adobe.com/go/getairsdk">http://www.adobe.com/go/getairsdk</a><br />
Unzip the SDK and place the folders in the location you prefer (macosx users will have to mount a .dmg image). Remember the location of the SDK, we will refer to it as <code>SDKPATH</code>.<br />
The directory of the SDK should look like this:
</p>
<div class="tutorial_image"><img src="http://nettuts.s3.amazonaws.com/083_adobeAirIntro/images/sdkFolders.png" border="0" /></div>
<h3>Step 4 &#8211; Configuration</h3>
<p>
The SDK has to be configured, otherwise the OS will not find the commands to be executed.<br />
In fact, if you open a shell a type <code>adl</code>, your OS will say something like &#8220;command not found&#8221;. This will work only if you move to the bin directory of the SDK folder. Since we want to be able to run build and test commands from every folder we have to configure the SDK. It is important to type correctly the absolute path of the bin directory in the SDK folder.
</p>
<p>On a Mac OS X follow this procedure:</p>
<ol>
<li/>Open the Terminal (/Applications/Utilities/Terminal)
<li/>Type <code>cd</code> to be sure you are in your home folder
<li/>look for a file named <code>.profile</code>. If it does not exist create it
<li/>Look for a line similar to this: <code>export PATH=$PATH:/usr/bin</code>
<li/>add another line like this: <code>export PATH=$PATH:/airsdk/bin</code>
<li/>if the path to the air SDK contains white spaces wrap it with a double quote (e.g. &#8220;/my pathtosdk/air&#8221;)
<li/>Close and reopen the terminal. Or type <code>source .profile</code>
</ol>
<p>
On Windows follow these steps:
</p>
<ol>
<li/>Right click on My Computer, choose Properties
<li/>Select the Advanced Tab and then click the Environment Variables button
<li/>Select <code>PATH</code> from the bottom list and add the path to the sdk folder at the end, as in figure.
</ol>
<div class="tutorial_image"><img src="http://nettuts.s3.amazonaws.com/083_adobeAirIntro/images/winSettings.png" border="0" /></div>
<p>To test whether the configuration is successful let&#8217;s open a shell and type the<br />
<code language="shell">adt</code> command.<br />
The result should be the following:
</p>
<div class="tutorial_image"><img src="http://nettuts.s3.amazonaws.com/083_adobeAirIntro/images/testAdt.png" border="0" /></div>
<p>
This response technically means that we have provided a wrong number of parameters to the command, but it also<br />
means that the SDK has been correctly installed and configured.
</p>
<h3>Step 5 &#8211; Project creation</h3>
<p>
Let&#8217;s now create our project folder. We call it myTest and we create two files: myTest.html and myTest.xml.</p>
<p>
The xml file is the configuration file, which enables setting up the air application. Open it with your preferred editor and insert the following code.</p>
<div class="tutorial_image"><img src="http://nettuts.s3.amazonaws.com/083_adobeAirIntro/images/xmlCode.png" border="0" /></div>
<p><br/><br/></p>
<p><!--</p>
<pre name="code" class="xml">
	<?xml version="1.0" encoding="utf-8" ?>
	<application xmlns="http://ns.adobe.com/air/application/1.0">
	    <id>com.spreadingfunkyness.myTest</id>
	    <filename>myTest</filename>
	    <name>My first Adobe Air App</name>
	    <description>An application to test Air sdk</description>
	    <version>0.1</version>

	    <initialWindow>
	        <content>myTest.html</content>

	        <systemChrome>standard</systemChrome>
<transparent>false</transparent>
	        <visible>true</visible>
	        <minimizable>true</minimizable>
	        <maximizable>true</maximizable>
	        <resizable>true</resizable>
	    </initialWindow>
	</application>
</pre>
<p>--></p>
<p>
The first line is a standard header for xml files. The second line starts the definition of our application. The <code>id</code> is the unique identifier of your application. In this case I prefixed that with my domain name. The <code>filename</code> is the name of the executable that we will generate. <code>Name</code> is the name of the application, as seen by the user. The <code>description</code> is a snippet which is shown during the installation to describe the application. <code>Version</code> indicates the version number of your app, 0.1 in our case. <br/><br />
After specifying metadata about the application we go to the definition of the graphics, enclosed in the <code><initialWindow></code> tag.
</p>
<p>
Line 10 specifies the root file, that is the file to be loaded in the air application at startup. In this case the myTest.html that we will show later. <code>Title</code> is the string that will appear in the upper part of the window. The <code>systemChrome</code> specifies whether your application has the standard chrome (the one of the hosting OS), or none. Chrome is a set of standard tools which allows manipulating a windows in a desktop environment, namely the title bar, close/resize buttons, borders and the area to grip for resizing.
</p>
<p>
The <code>background</code> of an Air application can be set to transparent, but this option is valid only if the chrome is set to none. Visible allows to decide whether you application should be displayed when launched. This is useful when the startup takes some time and you don't want to display the graphics to users.<br />
The meaning of tags <code>minimizable</code>, <code>maximizable</code> and <code>resizable</code> should be intuitive and should not need explanation.
</p>
<p>Now let's look at myTest.html which actually contains our application. </p>
<div class="tutorial_image"><img src="http://nettuts.s3.amazonaws.com/083_adobeAirIntro/images/html1.png" border="0" /></div>
<p><!--</p>
<pre name="code" class="html">
	<html>
		<head>

		</head>
	    <body>  
<div align="center">This is my first Air application.</div>

	    </body>
	</html>
</pre>
<p>-->
<p>
As you can see it is a standard html page, with a head and a body. The head contains a title and the body has a simple div with center-aligned text.
</p>
<h3>Step 6 - Running the application</h3>
<p>
Before packing the application as a .air file we will test it to check whether it produces the expected result.<br />
The tool we will use id <code>adl</code>, which allows to run our Air applications without installation.<br />
Let's open a shell and go to the directory which contains our myTest files (both html and xml).<br />
Then type the following command:
</p>
<pre name="code">
	adl myTest.xml
</pre>
<p>
This runs the application with the chrome of the current OS. On a MacOs should look like this.
</p>
<div class="tutorial_image"><img src="http://nettuts.s3.amazonaws.com/083_adobeAirIntro/images/myTestApplicationMac.png" border="0" alt="Your Air application running on MacOsx"/></div>
<p>
On Windows XP the application will appear like this:</p>
<div class="tutorial_image"><img src="http://nettuts.s3.amazonaws.com/083_adobeAirIntro/images/myTestApplicationWin.png" border="0" alt="Your Air application running on Windows XP" /></div>
<p>
You might doubt that this application works just with html. Let's test javascript.<br />
We change the <code>myTest.html</code> file as follows.</p>
<div class="tutorial_image"><img src="http://nettuts.s3.amazonaws.com/083_adobeAirIntro/images/html2.png" border="0" /></div>
<p><!--</p>
<pre name="code" class="html">
    <html>
	<head>

		<script>
			function myfunction() {
				alert("javascript is working!");
			}
		</script>
	</head>
	<body>
<div align="center">This is my first Air application.</div>

		<button type="button" onClick="myfunction()">test javascript</button>
	</body>
	</html>
</pre>
<p>--></p>
<p>
With respect to the previous version we added a script tag which contains the definition of a simple javascript function, <code>myfunction()</code>,popping up an alert (lines 4-8). We added a button to the body (line 12). The action associated with the button click is the <code>popme()</code> function. Let's save the file and run it, using the same command from the shell, <code>adl myTest.xml</code>
</p>
<p>
If we click the button we should see something like the following:
</p>
<div class="tutorial_image"><img src="http://nettuts.s3.amazonaws.com/083_adobeAirIntro/images/myTestApplicationJS.png" border="0" alt="Javascript runnning on Air application" /></div>
<h3>Step 7 - Deploying Air application</h3>
<p>
Once your application is ready for deployment we can create the .air file, which is the distribution package for Adobe Air applications.<br />
This file, which is based on zip compression, contains all the stuff needed to install air applications.<br />
An Air application has to be signed with a certificate. For widely distributed applications it is preferable to obtain a certificate from an authority like <a href="http://www.thawte.com">thawte</a>.<br />
Our purpose is just testing, so a self signed certificate is enough. The creation of a certificate can be done via the <code>adt</code> command. Open a shell, move to the project folder, and type this command:
</p>
<pre name="code">
	adt -certificate -cn mycertificate 1024-RSA mycertificatefile.p12 mysecretpass
</pre>
<p>
<code>adt -certificate -cn</code> is simply the syntax required by the command. The following table explains the values provided to the command.
</p>
<table border="1" cellspacing="0" cellpadding="5" >
<thead>
<tr>
<td><strong>Parameter Value</strong></td>
<td><strong>Explanation</strong></td>
</tr>
</thead>
<tbody>
<tr>
<td>mycertificate</td>
<td>The name of the certificate</td>
</tr>
<tr>
<td>1024-RSA</td>
<td>The encryption key of the certificate</td>
</tr>
<tr>
<td>mycertificatefile.p12</td>
<td>The file where the certificate is stored</td>
</tr>
<tr>
<td>mysecretpass</td>
<td>The password which protects your certificate</td>
</tr>
</tbody>
</table>
<p>
If you check the project folder you'll find a new file called <code>mycertificate.p12</code> which is the self-signed certificate we right created.<br />
The project folder should now contain three files as in the figure below.
</p>
<div class="tutorial_image"><img src="http://nettuts.s3.amazonaws.com/083_adobeAirIntro/images/cert.png" border="0" alt="Project folder with self-signed certificate" /></div>
<p>
Now we have all we need to create our .air file. We have to run a pretty long shell command. Don't panic. I'll explain every single word. First let's see it.
</p>
<p><code>adt -package -storetype pkcs12 -keystore mycertificate.p12 AIRHelloWorld.air AIRHelloWorld.xml AIRHelloWorld.html</code></p>
<p>
As above <code>adt -package</code> is the syntax of the command, <code>storetype</code> indicates the the format of the keystore. This is a pretty technical parameter. To be brief, since we generated a certificate according to the pkcs12 format we have to tell it to the compiler. Next we specify the certificate file, via the <code>-keystore</code> parameter. Finally, we provide the name of the resulting .air file, the xml file containing the application settings and the .html entry point file. When we issue this command we will be asked for the password entered during the creation of the certificate ("mysecretpass") in our case.<br />
We now have a .air file, which is the distribution format of our application. If we double click it the installation process will start.<br />
Installation goes through two simple steps as shown below.</p>
<div class="tutorial_image"><img src="http://nettuts.s3.amazonaws.com/083_adobeAirIntro/images/installation1.png" border="0" alt="Installation - First Step" /></div>
<p>
Notice that, since we self signed the certificate, the published Identity of the application if UNKNOWN.
</p>
<div class="tutorial_image"><img src="http://nettuts.s3.amazonaws.com/083_adobeAirIntro/images/installation2.png" border="0" alt="Installation - Second Step" /></div>
<p>
During the second step you can specify where to install the application and whether to start it when the installation is finished.</p>
<h3>Conclusion</h3>
<p>
In this tutorial we have introduced the Adobe Air framework and we have built our first Adobe Air application using Html/Js.<br />
In the next episodes we will see how to build the same application with Flex and Flash CS3.
</p>
<ul class="webroundup">
<li>Subscribe to the <a href="http://feeds.feedburner.com/nettuts" title="NETTUTS RSS Feed">NETTUTS RSS Feed</a> for more daily web development tuts and articles.</li>
</ul>
<p>
<script type="text/javascript"><!--digg_url = "post permalink (not digg url)"; // -->
</script><br />
<script src="http://digg.com/tools/diggthis.js" type="text/javascript"></script></p>
]]></content:encoded>
			<wfw:commentRss>http://net.tutsplus.com/tutorials/tools-and-tips/introduction-to-adobe-air/feed/</wfw:commentRss>
		<slash:comments>70</slash:comments>
		</item>
		<item>
		<title>10 Insanely Useful Django Tips</title>
		<link>http://net.tutsplus.com/tutorials/tools-and-tips/10-insanely-useful-django-tips/</link>
		<comments>http://net.tutsplus.com/tutorials/tools-and-tips/10-insanely-useful-django-tips/#comments</comments>
		<pubDate>Tue, 30 Sep 2008 19:33:10 +0000</pubDate>
		<dc:creator>Glen Stansberry</dc:creator>
				<category><![CDATA[Tools & Tips]]></category>

		<guid isPermaLink="false">http://nettuts.com/?p=974</guid>
		<description><![CDATA[<img src="http://nettuts.s3.amazonaws.com/081_django10/iceberg_prev.jpg">]]></description>
			<content:encoded><![CDATA[<p>There are quite a few great little tricks and tips one could use on their Django projects that would speed up development and save many headaches in the long run. From basic to obscure, these tips can help any skill-level of programmer become more adept with Django and all it&#8217;s glory.</p>
<p><span id="more-974"></span></p>
<p><a href="http://www.djangoproject.com/">Django</a> is an excellent framework for Python. While it may not get as much ink as other popular frameworks like <a href="http://nettuts.com/misc/ruby-on-rails-from-scratch-week-3/">Rails</a>, it is just as much a polished framework as any of <a href="http://en.wikipedia.org/wiki/List_of_web_application_frameworks">the rest</a>. It puts plenty of emphasis on the <a href="http://c2.com/cgi/wiki?DontRepeatYourself" title="DRY">DRY</a> principle (Don&#8217;t Repeat Yourself) in clean coding by automating many of the processes in programming.</p>
<h3>1. Use relative paths in the configuration</h3>
<p>For some reason, projects tend to be moved around in location from time to time. This can be an absolute bear to deal with if you don&#8217;t first plan ahead for the possibility. Rob Hudson has an excellent technique to ensure that your Django deployments can be moved around with ease, only having to edit a few lines of code in your settings files.</p>
<blockquote><p>My default Django settings file has changed over time to now include settings that do not depend on the location of the project on the file system. This is great in a team environment where more than one person is working on the same project, or when deploying your project to a web server that likely has different paths to the project root directory.</p></blockquote>
<p>Rob&#8217;s post has excellent <a href="http://rob.cogit8.org/blog/2008/Jun/20/django-and-relativity/">code examples</a> for setting up your Django installation in a very flexible way.</p>
<div class="tutorial_image"><img src="http://nettuts.s3.amazonaws.com/081_django10/1.jpg"><br/>Photo by <a href="http://www.flickr.com/photos/kaet44/">kaet44</a>.</div>
<h3>2. Use the {% url %} tag</h3>
<p>Instead of hardcoding individual links, try using the backwards compatible <a href="http://docs.djangoproject.com/en/dev/ref/templates/builtins/?from=olddocs#url">{% url %}</a> tag to achieve the same result. This will give you the <em>absolute</em> URL, so that if, heaven forbid, your Django project moves the links will still remain in tact.</p>
<p>Essentially the {% url %} takes a view name and its parameters and does a reverse lookup to return the queried URL. If you make changes to your urls.py file, the links won&#8217;t break.</p>
<p>While it&#8217;s not the most advanced tip, it&#8217;s an excellent technique to use in your django projects.</p>
<div class="tutorial_image"><img src="http://nettuts.s3.amazonaws.com/081_django10/2.jpg"><br/>Photo by <a href="http://www.flickr.com/photos/dave_apple/">Dave_Apple</a>.</div>
<h3>3. Use Django admin for your PHP apps</h3>
<p>Possibly one of the greatest features of Django is the <a href="http://docs.djangoproject.com/en/dev/topics/auth/#topics-auth" title="">user authentication</a> system that Django has built straight into the core. It&#8217;s seriously easy to set up, and it comes packed with a robust system to authenticate users and configure other necessary settings.</p>
<p>This user system is so awesome that it&#8217;s even been suggested to <a href="http://jeffcroft.com/blog/2006/jul/14/django-admin-your-php-app/<br />
">use Django as your admin area for your PHP application</a>. Here&#8217;s Jeff Croft on why Django is a great solution for an admin system for any application, regardless of language:</p>
<blockquote><p>One of the core philosophies of Django is loose coupling. Besides the more alluring free-love connotation, this mean that each of the layers of Django‚Äôs ‚Äústack‚Äù ought to be independent of the others, such that you can choose to use only bits and pieces of it, and/or slide in other components if you prefer. Lucky you, it‚Äôs incredibly simple to learn the basics of Django‚Äôs model layer, which handles database schema and object-relational mapping ‚Äî even if you don‚Äôt know Python. Anyone can create a database schema in Django and get the crown jewel of the framework &#8212; it&#8217;s admin interface &#8212; with very little work, even if you plan to write the application logic itself in another language.</p></blockquote>
<div class="tutorial_image"><img src="http://nettuts.s3.amazonaws.com/081_django10/3.jpg"><br/>Photo by <a href="http://www.flickr.com/photos/cloudzilla/">Cloudzilla</a>.</div>
<h3>4. Use a separate media server</h3>
<p>Django allows you to <a href="http://docs.djangoproject.com/en/dev/howto/static-files/#howto-static-files" title="">serve static files</a> in your development environment, but <strong>not your production environment</strong>. Why? It&#8217;s not efficient. At all. Jacobian.org <a href="http://www.jacobian.org/writing/2005/dec/12/django-performance-tips/" title="">gives an explanation</a>.</p>
<blockquote><p>Django deliberately doesn&#8217;t serve media for you, and it&#8217;s designed that way to save you from yourself. If you try to serve media from the same Apache instance that&#8217;s serving Django, you&#8217;re going to absolutely kill performance. Apache reuses processes between each request, so once a process caches all the code and libraries for Django, those stick around in memory. If you aren&#8217;t using that process to service a Django request, all the memory overhead is wasted.</p></blockquote>
<p>By using a separate server to house and serve these static files, your performance won&#8217;t suffer. If you didn&#8217;t want to buy a server you could use <a href="http://aws.amazon.com/s3/" title="">Amazon S3</a> to house the files relatively cheaply.</p>
<div class="tutorial_image"><img src="http://nettuts.s3.amazonaws.com/081_django10/4.jpg"><br/>Photo by <a href="http://www.flickr.com/photos/winkyintheuk/">winkyintheUK</a>.</div>
<h3>5. Use the Debugger Toolbar</h3>
<p>Debugging tools for any language are invaluable. They speed up development by spotting errors in your code and potential pitfalls that might happen. Rob Hudson has <a href="http://rob.cogit8.org/blog/2008/Sep/19/introducing-django-debug-toolbar/" title="">recently released</a> the <a href="http://github.com/robhudson/django-debug-toolbar/tree/master">django debug toolbar</a> to help with debugging code, and it could greatly help any developer.</p>
<blockquote><p>The toolbar itself is a piece of middleware that instantiates each panel object on request, and performs processing and rendering as the response is being written back to the browser. In this way it is essentially a set of middleware classes (the panels) grouped together to display a single toolbar. Each panel subclasses a base panel class and overrides a few methods to render the toolbar. </p></blockquote>
<div class="tutorial_image"><img src="http://nettuts.s3.amazonaws.com/081_django10/5.jpg"><br/>Photo by <a href="http://www.flickr.com/photos/winkyintheuk/">winkyintheUK</a>.</div>
<h3>6. Use Django Unit Testing</h3>
<p><a href="http://docs.djangoproject.com/en/dev/topics/testing/?from=olddocs<br />
">Unit testing</a> is a great way to ensure that your changes to the code that it works as expected and doesn&#8217;t break any older code to maintain backwards compatibility. A great feature in Django is that it&#8217;s incredibly easy to write unit tests. Django offers the ability to use the <a href="http://docs.python.org/lib/module-doctest.html">doctest</a> or <a href="http://docs.python.org/lib/module-unittest.html" title="">unittest</a> straight out of the box.</p>
<p>Django&#8217;s documentation offers a <a href="http://docs.djangoproject.com/en/dev/topics/testing/?from=olddocs">great tutorial</a> and some sample code on how to set up unit tests to keep your code running smoothly and spot any nasty bugs. </p>
<div class="tutorial_image"><img src="http://nettuts.s3.amazonaws.com/081_django10/6.jpg"><br/>Photo by <a href="http://www.flickr.com/photos/dave_apple/">dave_apple</a>.</div>
<h3>7. Use a Cheatsheet</h3>
<p>Is cheating wrong? I hope not. This nifty 2-page <a href="http://www.mercurytide.co.uk/whitepapers/django-cheat-sheet/">cheatsheet</a> contains some golden nuggets within arm&#8217;s reach that one might have to dig around the Django documentation to find.</p>
<p>The cheatsheet features these helpful topics:</p>
<p><strong>Templates</strong></p>
<ul>
<li>Template tags and their options</li>
<li>Template filters and their options</li>
<li>Date formatting syntax quick reference</li>
</ul>
<p><strong>Models</strong></p>
<ul>
<li>Fields and their options</li>
<li>Common field options</li>
<li>Meta class options</li>
<li>ModelAdmin options</li>
</ul>
<p><strong>Forms</strong></p>
<ul>
<li>Fields and their options</li>
<li>Common field options</li>
<li>Standard error_messages keys</li>
</ul>
<blockquote><p>We all know time spent looking at documentation is time spent not solving the world‚Äôs problems through code. And no good programmer wants that.</p></blockquote>
<div class="tutorial_image"><img src="http://nettuts.s3.amazonaws.com/081_django10/7.jpg"><br/>Photo by <a href="http://www.flickr.com/photos/tempus7/">quimpg</a>.</div>
<h3>8. Utilize django-chunks</h3>
<p><a href="http://code.google.com/p/django-chunks/">Django-chunks</a> is essentially a way to create blocks of reused code in your templates. Except creating the blocks is made even easier by using Django&#8217;s rich text editor. </p>
<blockquote><p>Well it essentially allows someone to define &#8220;chunks&#8221; (I had wanted to call it blocks, but that would be very confusing for obvious reasons) of content in your template that can be directly edited from the awesome Django admin interface. Throwing a rich text editor control on top of it make it even easier. </p></blockquote>
<p>By replicating bits of reusable code, django-chunks ensures that pieces of the layout can quickly and easily be changed if need be. While django-chunks is really only a model and template tag, it can greatly speed up development by replicating processes.</p>
<div class="tutorial_image"><img src="http://nettuts.s3.amazonaws.com/081_django10/8.jpg"><br/>Photo by <a href="http://www.flickr.com/photos/s_y_s/">Vince Huang</a>.</div>
<h3>9. Utilize Memcache</h3>
<p>If performance is going to be an issue with your Django-powered application, you&#8217;ll want to install some sort of caching. While Django offers <a href="http://docs.djangoproject.com/en/dev/topics/cache/" title="">many options for caching</a>, the best by far is <a href="http://docs.djangoproject.com/en/dev/topics/cache/#memcached" title="">memcached</a>. Installing and using memcached is fairly easy with Django if you use the <a href="http://gijsbert.org/cmemcache/" title="">cmemcache</a> module. Once the module is installed, you just change a single configuration option, and your Django pages will be served lighting fast.</p>
<div class="tutorial_image"><img src="http://nettuts.s3.amazonaws.com/081_django10/9.jpg"><br/>Photo by <a href="http://www.flickr.com/photos/cantchangerandy/">lastrandy</a>.</div>
<h3>10. Stop hacking scripts together and just use Django</h3>
<p>If you still don&#8217;t fully understand Django&#8217;s power after reading this article, there&#8217;s a logical reasoning for using Django in your next project: You save time hacking together designs with different sets of software. Jeff Croft explains why creating a project in Django is much <a href="http://jeffcroft.com/blog/2006/may/02/django-non-programmers/">more efficient than trying to hack together scripts</a>.</p>
<blockquote><p>Now, if you&#8217;re used to building sites using a blogging app (Wordpress, TXP, etc.) as a CMS, you&#8217;re used to getting all that for free. But you&#8217;re also getting a lot of things built-in that maybe you don&#8217;t want (unless, of course, you&#8217;re building a blog). The limitation I ran across in using a blogging app for my personal site is that I wanted it to be more than just a blog. As soon as I tried to hack a blog into a photo gallery, or a links feed, or a statistics database, a game of Sudoku, or whatever else I could think of, things started to get crufty. I also built a website in which I tried to use a discussion forums app (vBulletin) as a CMS, and that had the same results. It worked &#8212; sort of &#8212; but it wasn&#8217;t extensible, was very hackish, and just generally was inelegant.</p>
<p>With Django, you get all of these things and none of the limitations of a blogging app.</p></blockquote>
<p>Django allows you to expand your website into literally any direction without having to worry about hacking the design or making sure the scripts and databases are compatible. It just <em>works</em>.</p>
<div class="tutorial_image"><img src="http://nettuts.s3.amazonaws.com/081_django10/10.jpg"><br/>Photo by <a href="http://www.flickr.com/photos/diverslog/">JennyHuang</a>.</div>
<ul class="webroundup">
<li>Subscribe to the <a href="http://feeds.feedburner.com/nettuts">NETTUTS RSS Feed</a> for more daily web development tutorials and articles.</li>
</ul>
<p><em>
<p>Glen Stansberry is a web developer and blogger who&#8217;s struggled more times than he&#8217;d wish to admit with CSS. You can read more tips on web development at his blog <a href="http://www.webjackalope.com" title="Web Jackalope - web development tips">Web Jackalope</a>.</p>
<p></em></p>
<p><strong>If you found this post useful, please say thank you with a Digg or Stumble.</strong></p>
<p><script type="text/javascript"><!--
digg_url = "http://nettuts.com/web-roundups/10-insanely-useful-django-tips";
// --></script><br />
<script src="http://digg.com/tools/diggthis.js" type="text/javascript"></script></p>
]]></content:encoded>
			<wfw:commentRss>http://net.tutsplus.com/tutorials/tools-and-tips/10-insanely-useful-django-tips/feed/</wfw:commentRss>
		<slash:comments>34</slash:comments>
		</item>
		<item>
		<title>Evening Tip: 5 Time Saving Coda Features</title>
		<link>http://net.tutsplus.com/tutorials/tools-and-tips/5-time-saving-coda-features/</link>
		<comments>http://net.tutsplus.com/tutorials/tools-and-tips/5-time-saving-coda-features/#comments</comments>
		<pubDate>Wed, 27 Aug 2008 22:00:11 +0000</pubDate>
		<dc:creator>Sean Nelson</dc:creator>
				<category><![CDATA[Tools & Tips]]></category>
		<category><![CDATA[coda]]></category>
		<category><![CDATA[ftp]]></category>
		<category><![CDATA[mac]]></category>

		<guid isPermaLink="false">http://nettuts.com/?p=582</guid>
		<description><![CDATA[<img src="http://nettuts.s3.amazonaws.com/058_CodaTechniques/200x200.png" alt="5 Time Saving Coda Features" />]]></description>
			<content:encoded><![CDATA[<p>Panic Inc.&#8217;s application &#8220;Coda&#8221; is, in my opinion, a terrific application for the Mac OS X platform. It&#8217;s single window interface keeps things organized and eliminates the cluttered desktop that typically plagues web designers and programmers. What I like most about Coda is all of it&#8217;s time saving features. Here are my top 5:</p>
<p><span id="more-582"></span></p>
<h3>
        1. Built in reference guides.<br />
    </h3>
<div class="tutorial_image">
        <img src="http://nettuts.s3.amazonaws.com/058_CodaTechniques/one.jpg" border="0" /></div>
<p>
        Do you often find yourself pulling out your programming books for quick reference?<br />
        Coda helps save you a trip to the book shelf. Included are the HTML, CSS, Javascript,<br />
        and PHP “Web Programmer&#8217;s Desk Reference” reference guides. Even better, they are<br />
        searchable and integrated into the app&#8217;s Programming Hints banner.</p>
<p>
        Visit the Books section by clicking the Books button in the Toolbar or by pressing<br />
        Command+6.</p>
<h3>
        2. Blockedit</h3>
<div class="tutorial_image">
        <img src="http://nettuts.s3.amazonaws.com/058_CodaTechniques/two.jpg" border="0" /></div>
<p>
        This is probably my favorite feature. Hold down the Option key and select a block<br />
        of text (or an empty block) and start typing. Coda mimics the text you type to all<br />
        of the lines selected. This is perfect for adding a long list of links, lists, or<br />
        putting navs together.</p>
<p>
        There are a couple of different ways to do this. Select a block of text and go Text<br />
        > Blockedit Selection (Shift+Command+3), or just hold down Option while selecting<br />
        the text (the cursor will turn into a crosshairs).</p>
<h3>
        3. Clips</h3>
<div class="tutorial_image">
        <img src="http://nettuts.s3.amazonaws.com/058_CodaTechniques/three.jpg" border="0" /></div>
<p>
        Clips will store your favorite text clippings into an easy to reach widget. Coda<br />
        provides you with the famous Lorem Ipsum filler text and some Doctypes to start,<br />
        but you can easily add your own by pressing the Plus button at the bottom. Rather<br />
        than typing things over and over again, click and drag a clip to your document and<br />
        you&#8217;re done.</p>
<p>
        I use it to store my CSS document template and some common includes.</p>
<h3>
        4. Built in Code Validation</h3>
<div class="tutorial_image">
        <img src="http://nettuts.s3.amazonaws.com/058_CodaTechniques/four.jpg" border="0" /></div>
<p>
        Always visiting <a href="http://validator.w3.org/">validator.w3.org</a> to make<br />
        sure your HTML is good to go? Coda has HTML and XHTML code validation built in (sorry,<br />
        no CSS). Follow the warning triangles and read the balloons to get an idea of what&#8217;s<br />
        wrong. Coda will continue to re-validate your document as you edit it until it&#8217;s<br />
        turned off.</p>
<h3>
        5. Split Editing</h3>
<div class="tutorial_image">
        <img src="http://nettuts.s3.amazonaws.com/058_CodaTechniques/five.jpg" border="0" /></div>
<p>
        Split editing is great for when you need quick reference to other files without<br />
        needing to switch tabs. In your file browser on the left, Control+Click on a file<br />
        and choose Open in Split.</p>
<p>
        I like to have my CSS in one Split and my HTML in another. That way I always know<br />
        what elements I need to edit.</p>
<p>
        You can read more about Coda on <a href="http://www.panic.com/coda/">Panic&#8217;s Website</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://net.tutsplus.com/tutorials/tools-and-tips/5-time-saving-coda-features/feed/</wfw:commentRss>
		<slash:comments>49</slash:comments>
		</item>
		<item>
		<title>Build Your First Facebook App</title>
		<link>http://net.tutsplus.com/tutorials/tools-and-tips/build-your-first-facebook-app/</link>
		<comments>http://net.tutsplus.com/tutorials/tools-and-tips/build-your-first-facebook-app/#comments</comments>
		<pubDate>Wed, 20 Aug 2008 12:37:25 +0000</pubDate>
		<dc:creator>Joe Casabona</dc:creator>
				<category><![CDATA[Tools & Tips]]></category>
		<category><![CDATA[facebook app]]></category>

		<guid isPermaLink="false">http://nettuts.com/?p=471</guid>
		<description><![CDATA[<img src="http://nettuts.s3.amazonaws.com/049_CreateYourFirstFacebookApp/200x200.png" alt="Build Your First Facebook App" />]]></description>
			<content:encoded><![CDATA[<p>So you want to build a Facebook application and reach literally millions of users. Well luckily, writing an application using the API isn&#8217;t too hard to learn (for the basics, anyway). In this tutorial we will write a Facebook app that generates a random quote to display on the user&#8217;s profile. </p>
<p><span id="more-471"></span></p>
<div class="tutorial_image">
<a href="http://nettuts.s3.amazonaws.com/049_CreateYourFirstFacebookApp/src.zip"><br />
<img src="http://nettuts.com/wp-content/themes/nettuts/site_images/button_src_nm.jpg" alt=""></a><br />
<a href="http://apps.facebook.com/nettuts/" target="_blank"><br />
<img src="http://nettuts.com/wp-content/themes/nettuts/site_images/button_demo_nm.jpg" alt=""></a></div>
<h3>Getting Started</h3>
<p>It&#8217;s worth noting that the Facebook API is available to a number of languages, all listed on the <a href="http://wiki.developers.facebook.com/index.php/Main_Page">Facebook Developers Wiki</a>. I will be using PHP 5 for this tut. You will also need to download the <a href="http://svn.facebook.com/svnroot/platform/clients/packages/facebook-platform.tar.gz">PHP 5 Client Library</a>, which I&#8217;ve included in the SRC files. All code featured here will be in the index.php file.</p>
<h3>Step 1: Initialize Your App</h3>
<p>The first step to get a Facebook API key, which allows your app to retrieve information from Facebook. Go to the <a href="http://www.new.facebook.com/developers/">Facebook Developer Application</a> and click the &#8220;Set Up a New Application&#8221; button. Pick a name, agree to the Terms &amp; Conditions, and you&#8217;ve got your API. Now you need to set up your canvas page name and callback URL.</p>
<div class="tutorial_image"><img src="http://nettuts.s3.amazonaws.com/049_CreateYourFirstFacebookApp/developer-page.jpg" border="0" /></div>
<p>Your canvas page is the application area within Facebook; the name is added to the URL and will look like this: <code>http://apps.new.facebook.com/[YOUR APP NAME]</code>. The callback URL points to the server hosting the app files. To set these up, from the &#8220;My Applications&#8221; page click &#8220;Edit Settings&#8221; on the right hand side. You will see the fields to fill in both, as I did in the screen shot below. While there are lots of other options, none are necessary for this tutorial. Click &#8216;Save&#8217; and you&#8217;re now ready to build your first Facebook app. Facebook even provides you with some start up code. I&#8217;ve cut out the extra stuff and gave you only what you need to initialize your app&#8230;</p>
<div class="tutorial_image"><img src="http://nettuts.s3.amazonaws.com/049_CreateYourFirstFacebookApp/edit.jpg" border="0" /></div>
<pre name="code" class="php">
&lt;?php

require_once 'includes/facebook.php';

$appapikey = '85e4cd7042467d0b20109aafb6f20117';
$appsecret = 'be5a528d73ad191b6b21a84c4af054ee';
$facebook = new Facebook($appapikey, $appsecret);
$user_id = $facebook-&gt;require_login();
$callbackurl = 'http://www.casabona.org/nettuts/';

?&gt;
</pre>
<p>This is fairly straight-forward code. We create a Facebook object using our API key and app secret, which was given to us when we created the API key. The first thing we do after that is get the user id of the logged in user. This will be valuable to us if we were do things get the user&#8217;s name, the user&#8217;s friends, etc. I&#8217;ve also added the <code>$callbackurl</code> to make it easier to link to images or other files, as Facebook does not allow relative linking.</p>
<h3>Step 2: Writing the Application</h3>
<p>If we don&#8217;t make specific Facebook calls, this is just like writing a php application. Below is our code.</p>
<pre name="code" class="php">
//initialize an array of quotes
$quotes= array("Only those who dare to fail greatly can ever achieve greatly.", "Take my wife. Please!", "I believe what doesn't kill you only makes you... STRANGER");

//Select a Random one.
$i= rand(0, sizeof($quotes)-1);

//print the CSS
print ('
&lt;style type="text/css"&gt;
 h1{ margin: 10px; font-size: 24pt; }
 h2{ margin: 15px; font-size: 20pt; }
&lt;/style&gt;
');

print "&lt;h1&gt;Nettuts Quotes&lt;/h1&gt;";
print "&lt;h2&gt;". $quotes[$i] ."&lt;/h2&gt;";
</pre>
<p>This is all you need to do to print to the canvas page. One thing to note is the way we create CSS. We cannot call a file like style.css- we actually have to include the CSS in the HTML. This is so our CSS doesn&#8217;t interfere with Facebook&#8217;s. You should also know that when styling divs, you can only uses class, not id. The code we created will produce something like this:</p>
<div class="tutorial_image"><img src="http://nettuts.s3.amazonaws.com/049_CreateYourFirstFacebookApp/canvas.jpg" border="0" /></div>
<h3>Step 3: Creating the Profile Box</h3>
<p>Finally, some Facebook specific stuff. The code below is necessary to add our quote to the user&#8217;s profile, granted they are displaying our app in their profile. In our app, I&#8217;ve added the follow code right below <code>$i= rand(0, sizeof($quotes)-1);</code></p>
<pre name="code" class="php">
//prepare string for profile box
$text= ('
&lt;style type="text/css"&gt;
 h1{ margin: 10px; font-size: 24pt; }
 h2{ margin: 15px; font-size: 20pt; }

&lt;/style&gt;
');

$text.=('&lt;h2&gt;'. $quotes[$i] .'&lt;/h2&gt;');

//set profile text
$facebook->api_client->profile_setFBML($text, $user_id);
</pre>
<p>Notice I&#8217;ve done two things here: reprinted the CSS and put everything in a string called <code>$text</code>. This is because the function that sets the profile box text, <code>profile_setFBML</code>, takes two arguments: the text that should go in the profile box, and the id of the user. Any CSS defined for the canvas page is not transferred to the profile, so we must also add that to our first argument. The end result is this:</p>
<div class="tutorial_image"><img src="http://nettuts.s3.amazonaws.com/049_CreateYourFirstFacebookApp/profile.jpg" border="0" /></div>
<h3>That&#8217;s It!</h3>
<p>We&#8217;ve obviously only scratched the surface as far as Facebook application development goes. However, with the Wiki and resources Facebook gives you when you get an API key, you should be well on your way to creating the next big app! If you want to check out this app in all its glory, you can go <a href="http://apps.facebook.com/nettuts/">here</a>, just so long as you have a Facebook account.</p>
]]></content:encoded>
			<wfw:commentRss>http://net.tutsplus.com/tutorials/tools-and-tips/build-your-first-facebook-app/feed/</wfw:commentRss>
		<slash:comments>78</slash:comments>
		</item>
		<item>
		<title>Learn How To Develop For The iPhone</title>
		<link>http://net.tutsplus.com/tutorials/tools-and-tips/learn-how-to-develop-for-the-iphone/</link>
		<comments>http://net.tutsplus.com/tutorials/tools-and-tips/learn-how-to-develop-for-the-iphone/#comments</comments>
		<pubDate>Mon, 18 Aug 2008 14:47:24 +0000</pubDate>
		<dc:creator>James Black</dc:creator>
				<category><![CDATA[Tools & Tips]]></category>
		<category><![CDATA[iphone]]></category>
		<category><![CDATA[mobile]]></category>

		<guid isPermaLink="false">http://nettuts.com/?p=443</guid>
		<description><![CDATA[<img src="http://nettuts.s3.amazonaws.com/048_Iphone/200x200.png" alt="Developing For The IPhone" />]]></description>
			<content:encoded><![CDATA[<p>
Today I&#8217;m going to show you how to build an alternate page and style sheet for the iPhone and iTouch. We will cover how to detect if the user is using an iPhone to view your page as well as the orientation of the device &#8211; whether it be landscape or portrait. To accomplish this we will be using javascript, and some Safari mobile specific CSS tags.  <span id="more-443"></span>
</p>
<p><!--more--></p>
<h3>Getting Started</h3>
<p>We&#8217;re going to start off with 2 psd&#8217;s I made and get those working in an iPhone page. I am using images for the background and header although you could use just straight colors instead of images. The plus side to not using images is that it obviously loads faster but also when switching between landscape and portrait the images take a moment to load, depending on how large they are. You can find the <a href="http://nettuts.s3.amazonaws.com/048_Iphone/source_files.zip">source psd files here</a> or you can make your own. Something to keep in mind is that we are building a page specifically for the iPhone or iTouch. If you do not have the device yourself you can download the iPhone SDK freely from Apple and it includes an iPhone simulator. if you would like to detect the iPhone on your standard browser page and either load the iPhone css and html through conditional statements or send the user to a different page entirely, use the following code:</p>
<div class="tutorial_image">
<img src="http://nettuts.s3.amazonaws.com/048_Iphone/tut_images/portrait.jpg" border="0" /></div>
<pre name="code" class="js">
&lt;script type="text/javascript">
var browser=navigator.userAgent.toLowerCase();
var users_browser = ((browser.indexOf('iPhone')!=-1);
if (users_browser)
{
	document.location.href='www.yourdomain.com/iphone_index.html';
}
&lt;/script>
</pre>
<p>The code above explained:</p>
<ul>
<li>Line 2: Create a variable that holds the users type of browser ( among other things )</li>
<li>Line 3: Assign the browser type a value if the iPhone browser is present. </li>
<li>Line 4 &#8211; 8: An if statement that redirects the user to an &#8220;iPhone formated page&#8221; if the variable &#8220;users_browser&#8221; returns a value ( meaning the user is using an iPhone or iTouch to view the current page ).</li>
</ul>
<p> Below the code will use html conditional statements to hide the code from a regular browser. </p>
<pre name="code" class="html">
	&lt;!--#if expr="(${HTTP_USER_AGENT} = /iPhone/)"-->

	&lt;!--
	place iPhone code in here
	-->

	&lt;!--#else -->

	&lt;!--
		place standard code to be used by non iphone browser.
	-->
	&lt;!--#endif -->
</pre>
<h3>Step 1: The HTML</h3>
<p>So we now know how to point the user to your iPhone page if they are on an iPhone or iTouch device. Now, we will start working on the iPhone HTML page; the code below has some key differences from a regular XHTML transitional document.</p>
<pre name="code" class="html">
	&lt;!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
		"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

	&lt;html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
	&lt;head>
		&lt;meta name="viewport" content="width=device-width; initial-scale=1.0; maximum-scale=1.0;">

		&lt;title>My iPhone Page&lt;/title>

		&lt;link rel="apple-touch-icon" href="images/myiphone_ico.png"/>
		&lt;link rel="StyleSheet" href="css/iphone_portrait.css" type="text/css"  media="screen" id="orient_css">
</pre>
<p>The code above explained line by line:</p>
<ul>
<li>Line 1 &#8211; 5: This is standard 1.0 XHTML Transitional Doctype. Nothing special yet.</li>
<li>Line 6: This line is iPhone and iTouch specific. It sets initial values for the viewport in the Device&#8217;s browser. width=device-width states the width of the page to be the same width of the device. initial-scale and maximum scale set the starting point for the zoom of the page, maximum-scale is how much the page cane be scaled up.</li>
<li>Line 9: This link element is pointing to the web pages icon. this is used when a user saves the page to their &#8220;Home Screen&#8221;. </li>
<li>Line 10: A link element points to the iPhone style sheet. This element has the id orient_css assigned to it. This is so that we can point to it with javascript to change the css file it points to when it comes to adjusting the layout for the orientation of the device.  </li>
</ul>
<h3>Step 2: Laying Out The Divs</h3>
<p>We now continue with the rest of the html before we add any javascript functions for orientation detection. Start with ending the head and then start the body. In the body element we add onorientationchange=orient();. So I just lied, that is a bit of javascript, but this is needed to call our &#8220;orient&#8221; function (we&#8217;ll go over this in a bit) when ever the device detects a different orientation. </p>
</p>
<pre name="code" class="html">

	&lt;/head>

	&lt;body onorientationchange="orient();">

		&lt;div id="wrap">
			&lt;div id="header">
			&lt;/div>
			&lt;div id="content">
			&lt;p>This is the main content area of the page. &lt;/p>
			&lt;p>Using css and javascript we can manipulate any of these divs using an alternate css file. The css files in this project are for landscape and portrait views.&lt;/p>
			&lt;p>Some more filler text here to demonstrate the page.&lt;/p>
			&lt;/div>
			&lt;div id="bottom">
			&lt;/div>
		&lt;/div>
	&lt;/body>
	&lt;/html>
</pre>
<h3>Step 3: The Orientation Javascript</h3>
<p>In the head of the page you will want to place the code seen below</p>
<pre name="code" class="js">
		&lt;script type="text/javascript">
		function orient()
		{
			switch(window.orientation){
					case 0: document.getElementById("orient_css").href = "css/iphone_portrait.css";
			        break;

					case -90: document.getElementById("orient_css").href = "css/iphone_landscape.css";
				    break;

					case 90: document.getElementById("orient_css").href = "css/iphone_landscape.css";
					break;

		}
	}
		window.onload = orient();

		&lt;/script>
</pre>
<p>switch(window.orientation) works off of the onorientationchange() method in the body element. This will check to see if the current rotation is equal to the &#8220;case value&#8221;, if it returns true it will execute what is after the colon. After an orientation has been matched it breaks out of orient();. window.onload() runs the orient function when the page first finishes loading.</p>
<p>After each case (value) : we have javascript pointing to the link elements id that our css file is attached to. Depending on the case value, 0, 90 or -90 ( there is also 180 but it is not supported on the iPhone at this time) the portrait or landscape css file is attached to the href tag in the link element. 0 is upright (portrait), 90 is landscape counter clockwise. -90 is landscape turned clockwise and 180 although not supported yet would represent the device being upside down. </p>
<h3>Step 4: Implementing The CSS</h3>
<p>Even with all of this code, the page doesn&#8217;t do much. That&#8217;s because we need to add background images and style it all. We will create 2 css files, one called iphone_portrait.css and another called iphone_landscape.css. We will place the portrait css file into the link element as the default css file to use.  </p>
<pre name="code" class="css">

	body
	{
		background-color:#333;
		margin-top:-0px;
		margin-left:-0px;
	}

	#wrap
	{
		overflow:auto;
		width:320px;
		height:480px;

	}

	#header
	{
		background:url(../images/header.jpg);
		background-repeat:no-repeat;
		height:149px;

	}

	#content
	{
		background:url(../images/middle.jpg);
		background-repeat:repeat-y;
		margin-top:-5px;

	}

	p
	{
		margin:5px;
		padding-left:25px;
		width:270px;
		font-size:10px;
		font-family:arial,"san serif";
	}

	#bottom
	{
		background:url(../images/bottom_corners.jpg);
		background-repeat:no-repeat;
		height:31px;
		margin-top:-5px;
	}
</pre>
<p>The above code is for the iphone_portrait.css file and is rather straight forward. Some things to note are:</p>
<ul>
<li>in the wrap style description overflow:auto makes sure floated items are kept inside the wrap div to keep the page nice and tidy.</li>
<li> the dimensions for the page are 320px wide by 480px tall. be sure to state this in the wrap div.  </li>
</ul>
<p>Below is the code to be placed inside the iphone_landscape.css file. the only differences between portrait and landscape css files are the background images, the wrap dimensions are reversed and the margins are adjusted accordingly.</p>
<pre name="code" class="css">
	body
	{
		background-color:#333;
		margin-top:-0px;
		margin-left:-0px;
	}

	#wrap
	{
		overflow:auto;
		width:480px;
		height:320px;

	}

	#header
	{
		background:url(../images/l_header.jpg);
		background-repeat:no-repeat;
		height:120px;

	}

	#content
	{
		background:url(../images/l_middle.jpg);
		background-repeat:repeat-y;
		margin-top:-5px;

	}

	p
	{
		margin:5px;
		padding-left:25px;
		width:370px;
		font-size:10px;
		font-family:arial,"san serif";
	}

	#bottom
	{
		background:url(../images/l_bottom_corners.jpg);
		background-repeat:no-repeat;
		height:37px;
		margin-top:-5px;
	}
</pre>
<p>If you are using my sliced background images your page should now look like the image below when in portrait mode.</p>
<div class="tutorial_image"><img src="http://nettuts.s3.amazonaws.com/048_Iphone/tut_images/portrait_on_iphone.jpg" border="0" /></div>
<p>Or, in landscape mode?</p>
<div class="tutorial_image">
<img src="http://nettuts.s3.amazonaws.com/048_Iphone/tut_images/landscape_on_iphone.jpg" border="0" /></div>
<h3>Where To Go From Here?</h3>
<p>So now that you have a page formatted and styled for the iPhone and iTouch, what else can you do? Well, if your page is meant to be more of a web app you may want to check out the IUI by Joe Hewitt which is a framework that makes your pages look like native iPhone or iTouch apps. Also keep in mind that you can set 3 specific css files; so you can have one css file that styles the page if its turned clockwise to landscape and a different file again for when its turned counter clockwise to landscape. This will allow for some interesting outcomes. Good luck! </p>
]]></content:encoded>
			<wfw:commentRss>http://net.tutsplus.com/tutorials/tools-and-tips/learn-how-to-develop-for-the-iphone/feed/</wfw:commentRss>
		<slash:comments>100</slash:comments>
		</item>
		<item>
		<title>Integrating and Customizing Lijit for Your Site</title>
		<link>http://net.tutsplus.com/tutorials/tools-and-tips/integrating-and-customizing-lijit-for-your-site/</link>
		<comments>http://net.tutsplus.com/tutorials/tools-and-tips/integrating-and-customizing-lijit-for-your-site/#comments</comments>
		<pubDate>Mon, 04 Aug 2008 20:26:44 +0000</pubDate>
		<dc:creator>Thord Hedengren</dc:creator>
				<category><![CDATA[Tools & Tips]]></category>
		<category><![CDATA[lijit]]></category>

		<guid isPermaLink="false">http://nettuts.com/?p=94</guid>
		<description><![CDATA[<img src="http://nettuts.s3.amazonaws.com/032_Lijit/titlePic.png" alt="Lijit" />]]></description>
			<content:encoded><![CDATA[<p>Search is an important part of any website, and a lacking search functionality will mean that your visitors won&#8217;t find what they&#8217;re looking for, never a good thing. If you&#8217;re a WordPress user, you know what it is like, because WordPress, like so many other online publishing platforms, just can&#8217;t be as good as Google is. However, there are solutions. You can swap your search solution with something else, be it Google Co-Op, or Lijit. In this tutorial, we&#8217;ll take a look at Lijit, which will let you search across several sites, as well as multiple social webapps out there.
</p>
<p><span id="more-94"></span></p>
<p>
Lijit sparked my attention as a serious option to the overall pretty excellent Google Co-Op<br />
solution with their inclusion of the social sphere. I can easily add my YouTube, Flickr, Twitter<br />
account, and a lot more above that, for inclusion in the search queries sent through the Lijit<br />
search box on my site. That way, a user can search across all my presences online, bringing them<br />
closer together. That is, of course, a good thing.
</p>
<p><h2>The Brief</h2>
<p>I&#8217;ll use my own site, tdhedengren.com, as an example for this tutorial. It is in a sort of<br />
redesign mode, far from finished, which means that it is OK to play with it. Actually, it would be anyway, it is mine after all, but that&#8217;s beside the point. I&#8217;m running WordPress, but there won&#8217;t be any WordPress specifics in this tutorial, since it doesn&#8217;t matter to Lijit. I&#8217;ve got the search functionality from WordPress already, but I&#8217;m removing it in favor of Lijit.</p>
<p><strong>So let&#8217;s get started!</strong></p>
<h2>Step 1 &#8211; Getting Lijit</h2>
<p>
Signing up to Lijit is ridiculously easy. Just visit <a href="http://www.lijit.com">lijit.com</a> and type your URL in the field, and you&#8217;ll be thrown into a guide where you can tell Lijit where you&#8217;ve got an online presence, add blogs and sites you want to be included in the search, beside your own of course, and things like that. In fact, you can even ask Lijit to pull the blogs from your blogroll into your search, a nifty feature if any.
</p>
<div class="tutorial_image">
<img src="http://nettuts.s3.amazonaws.com/032_Lijit/lijitsignup.png" alt="Lijit Signup" style="width: 600px;" />
</div>
<p>
The list of online services is easily edited. Just click tha checkbox and fill out your username (you&#8217;ll get a check link when done typing, to make sure it is the right user on that particular online service), and you&#8217;re done.
</p>
<p>
There are a lot of online services and places to choose from, including MyBlogLog, Digg, Viddler, Tumblr, Disqus, Reddit, Facebook, and a bunch others, beside the ones already mentioned. And should your online poison not be there, you can always submit an URL or RSS feed, and Lijit will add it to the network.
</p>
<div class="tutorial_image">
<img src="http://nettuts.s3.amazonaws.com/032_Lijit/lijitcheckboxes.png" alt="Lijit checkboxes" style="width: 600px;"  />
</div>
<p>
These things are pretty straight forward. When you&#8217;re done, you can get your Search Wijit, which is the search box we want to integrate on our site. If you get lost in all the account settings and other things, just click the link in the top top right called My Search Wijit and you&#8217;re good to move on to step 2.
</p>
<h2>Step 2 &#8211; Integrating the Search Wijit</h2>
<p>
It is easy enough to get the Lijit search box, called the Search Wijit, on your site. Just click My Search Wijit in the top right when logged in, choose a Wijit Style, color, and logo color, make some other pretty obvious picks (add/remove features like a popular searches keyword cloud, icons, and so on), and save the settings. Clicking Install the Wijit button will get you your code, and then you just need to copy-paste this to where on your site you want the Lijit search box to be. It is simple enough. When installed, you won&#8217;t have to install it again, you just change your settings and save, and it is there automatically on your site, since everything is fetched from the Lijit servers.
</p>
<p>
However, let&#8217;s not get ahead of ourselves. Back to my blog. I wanted the Lijit search box up right away, so I unchecked all the extra features (content icons and so on), picked the Big Rounded style, Grey color, and Grayscale for the logo color option. The preview shows how it&#8217;ll look, but I put it up anyway, setting the width of the Search Wijit to 280 which I know would fit my sidebar.
</p>
<div class="tutorial_image">
<img src="http://nettuts.s3.amazonaws.com/032_Lijit/mylijitsettings.png" alt="My Lijit Settings" />
</div>
<p>
Simple enough, right. Clicking Install the Wijit gives me a page where I can do quick installs if I have a TypePad or Blogger blog, but since I&#8217;m a WordPress user, I get a simple JavaScript code snippet to include.
</p>
<pre name="code" class="js">
&lt;script type="text/javascript" src="http://www.lijit.com/informers/wijits?username=tdhedengren&#038;js=1">&lt;/script>
&lt;a style='color: #999' href='http://www.lijit.com' id='lijit_wijit_pvs_link'>Lijit Search&lt;/a>
</pre>
<p>
Since I think that the Lijit logo is enough, I removed the link, and then pasted this code in my sidebar, where I previously had the WordPress native search box.
</p>
<pre name="code" class="js">
&lt;script type="text/javascript" src="http://www.lijit.com/informers/wijits?username=tdhedengren&#038;js=1">&lt;/script>
</pre>
<p>
Simple as that, I&#8217;ve got an integrated search solution powered by Lijit. The great thing is that search results are served in a layer floating above my site, which means that visitors searching for something on my blog won&#8217;t have to leave, unless they get a hit from any of my other online presences (be it a story on Devlounge, a tweet, or something else from my network), which then will lead to this place, of course.
</p>
<div class="tutorial_image">
<img src="http://nettuts.s3.amazonaws.com/032_Lijit/basiclijit.png" alt="Basic Lijit" style="width: 600px;"  />
</div>
<div class="tutorial_image">
<img src="http://nettuts.s3.amazonaws.com/032_Lijit/lijitsearchresult.png" alt="Lijit Search Result" style="width: 600px;"  />
</div>
<p>
Simple as that, it took a few minutes playing around to get my very own Lijit search on my site.
</p>
<p>
Just for fun, let&#8217;s see how the search box would look with all extra bling-bling enabled, like keyword clouds, extra buttons and icons, and so on.
</p>
<div class="tutorial_image">
<img src="http://nettuts.s3.amazonaws.com/032_Lijit/lijitbling.png" alt="Lijit Bling" />
</div>
<p>
No, I don&#8217;t want that, it is too much for me. I like the more minimalistic approach, serving up content from all my online presences when people ask for it (ie search), rather than pushing it forward in this way. But that&#8217;s up to you, you might like it!
</p>
<h2>Step 3 &#8211; Customizing the Search Wijit for Your Design</h2>
<p>
While I do think that the Lijit search box looks OK with these basic settings, naturally, I&#8217;d like it a bit more customized for my design. This is done by adding some CSS to your stylesheet, which will control the design of the Lijit box just as it would when doing a traditional search form.
</p>
<p>
However, before you can do this, we&#8217;ll need to visit the My Search Wijit page again, and choose Style My Own from the Wijit Style dropdown menu, and save. This will change the Lijit search box to something we can style using CSS.
</p>
<div class="tutorial_image">
<img src="http://nettuts.s3.amazonaws.com/032_Lijit/lijitstyleyourown.png" alt="Lijit- Style Your Own" style="width: 600px;"  />
</div>
<div class="tutorial_image">
<img src="http://nettuts.s3.amazonaws.com/032_Lijit/basicstyleyourown.png" alt="Basic Style Your Own" style="width: 600px;"  />
</div>
<p>
Not too pretty anymore, but we&#8217;ll fix that. For me, I want a clean and simple form just like the ones I have for posting comments and whatnot on my site. There is not many CSS elements we need to mess with.
</p>
<ul>
<li>#lwp_main is the main div container</li>
<li>#lwp_sfb is the form</li>
<li>#lwp_sfd is the input box</li>
<li>#lwp_2_searchbutton is the submit button</li>
<li>#lwp_ps is the container for the search cloud</li>
</ul>
<p>
By adding these to your stylesheet, you can easily style the Lijit search box to fit your design. I just did some minor edits:
</p>
<pre name="code" class="css">
#lwp_main { float:right; width: 130px; text-align:right; } /* main div */
#lwp_sbf { overflow:hidden; margin:0; padding:0; } /* the form */
#lwp_sfd { width: 110px !important; margin-bottom: 3px; padding: 2px; border: 1px solid #555; text-align:right; } /* the input box */
#lwp_2_searchbutton { background: #555; color: #fff; font-size: 12px; font-weight:bold; border: 0; text-transform: lowercase; } /* the submit button */
#lwp_2_searchbutton:hover { background:#0c1; }
#lwp_ps {} /* the container for the search cloud */
#lwp_f { width: 130px !important; }
</pre>
<p>
The result is a floated little search box in my larger search box. Since #lwp_main is the containing div, I used that one for this, and put in my own code to float a div with the small informational type to the left. Naturally, you can do a lot more fancy stuff using the custom CSS, so find whatever fits your site and go with it. Most likely, all you&#8217;ll need to do is take your current code for your searchbox, and put this in the corresponding Lijit CSS element in your stylesheet.
</p>
<div class="tutorial_image">
<img src="http://nettuts.s3.amazonaws.com/032_Lijit/mylijit.png" alt="My Lijit" />
</div>
<h2>Step 4 &#8211; Search Result Variations</h2>
<p>
Personally, I like the layered div that displays the search result above my design. However, if you want to really embed the search result on your site, this is possible to. It works pretty much like Google Co-Op, which means that you&#8217;ll create a page on your site containing a code snippet that will display your result.
</p>
<p>
Setting it up is a breeze. Just go to My Search Wijit and chose On my blog (advanced) in the Display search results dropdown. Then write the URL to your search result page, and paste the code listed in the box below on this page. That&#8217;s it, very simple, just don&#8217;t forget to save your settings.
</p>
<div class="tutorial_image">
<img src="http://nettuts.s3.amazonaws.com/032_Lijit/lijitcustomresults.png" alt="Custom Results" />
</div>
<p>
<strong>Finished!</strong> That&#8217;s it! As you can see, the amount of work needed to get a working Lijit search on your site is minimal. If you want to customize it, you&#8217;ll need to mess around a bit more, but it is really more of an issue with your current site&#8217;s code and design, rather than something clunky in Lijit&#8217;s interface.
</p>
<p>
The pro and cons of going with Lijit rather than Google Co-Ops can be discussed, of course. The latter offer the option to include your very own Adsense code, which could generate some money, but Lijit has got the social web thing going in a cooler way. If you&#8217;ve made this choice, feel free to share your reasoning, as well as your verdict should you have one.
</p>
<p>
Happy searching!</p>
]]></content:encoded>
			<wfw:commentRss>http://net.tutsplus.com/tutorials/tools-and-tips/integrating-and-customizing-lijit-for-your-site/feed/</wfw:commentRss>
		<slash:comments>21</slash:comments>
		</item>
		<item>
		<title>Can You Hack Your Own Site? A Look at Some Essential Security Considerations</title>
		<link>http://net.tutsplus.com/tutorials/tools-and-tips/can-you-hack-your-own-site-a-look-at-some-essential-security-considerations/</link>
		<comments>http://net.tutsplus.com/tutorials/tools-and-tips/can-you-hack-your-own-site-a-look-at-some-essential-security-considerations/#comments</comments>
		<pubDate>Thu, 17 Jul 2008 05:38:25 +0000</pubDate>
		<dc:creator>Ben Charnock</dc:creator>
				<category><![CDATA[Tools & Tips]]></category>

		<guid isPermaLink="false">http://nettuts.com/?p=51</guid>
		<description><![CDATA[<img src="http://nettuts.s3.amazonaws.com/Articles/009_Security/NETTUTS-SEC/200.jpg">]]></description>
			<content:encoded><![CDATA[<p>Version one goes gold! Visitors are landing from every corner of the globe. You know there are likely to be a few teething problems, I mean, this is 1.0.0.0&#8230; all those zeroes are meant to allow us a little grace right?</p>
<p><span id="more-51"></span></p>
<p>Maybe that dastardly style sheet just won’t cascade<br />
elegantly on browser X. An incomplete comment chucks out some broken mark-up.<br />
Maybe you should have persisted those database<br />
connections after all. Hey, we all overlook things in the excitement of getting<br />
our first version running – but how many of these oversights can we happily<br />
stomach, and how many might just leave a bitter taste in ours, and more<br />
painfully our client’s mouths&#8230;</p>
<p>This article walks through the brainstorming stage of<br />
planning for what is in this instance, a hypothetical user-centric web<br />
application. Although you won’t be left with a complete project – nor a market<br />
ready framework, my hope is that each of you, when faced with future workloads,<br />
may muse on the better practices described. So, without further ado&#8230;Are you sitting<br />
comfortably?</p>
<h2><b>The Example</b></h2>
<p>We’ve been asked by our client to incorporate into an existing site, a book review system. The site already has user accounts, and<br />
allows anonymous commentary. </p>
<p>After a quick chat with the client, we have the following<br />
specification to implement, and only twenty four hours to do it:</p>
<div class="tutorial_image"><img  src="http://nettuts.s3.amazonaws.com/Articles/009_Security/NETTUTS-SEC/mainpages/spec.gif" width="600" height="420"></div>
<p><i>Note: The client&#8217;s server is running PHP5, and MySQL<br />
– but these details are not critical to understanding the bugbears outlined in<br />
this article.</i></p>
<h2><b>The Processes:</b></h2>
<div class="tutorial_image"><img  src="http://nettuts.s3.amazonaws.com/Articles/009_Security/NETTUTS-SEC/mainpages/flow a.gif" width="600" height="600"></div>
<p>Our client has given us a <b>PHP include</b> to gain access to the database:</p>
<div class="tutorial_image"><img  src="http://nettuts.s3.amazonaws.com/Articles/009_Security/NETTUTS-SEC/mainpages/flow a - php db connect.gif" width="600" height="144"></div>
<div class="tutorial_image"><img src="http://nettuts.s3.amazonaws.com/Articles/009_Security/NETTUTS-SEC/notepages/note mysql_pconnect.gif" width="600" height="75"><img src="http://nettuts.s3.amazonaws.com/Articles/009_Security/NETTUTS-SEC/notepages/note php include.gif" width="600" height="75"></div>
<p>We don’t actually need the source to this file to use it. In fact, had the client merely told us where it lived we could have used it with<br />
an include statement and the <i>$db</i><br />
variable.</p>
<p>On to authorisation&#8230; within the datatable schema we are concerned with the following column names:</p>
<ul>
<li>
  <b>username</b>, varchar(128) &ndash; stored as plain text.</li>
<li>
    <b>password</b>, varchar(128) &ndash; stored as plain text.</li>
</ul>
<p>Given that we’re working against the clock&#8230; let’s write a<br />
PHP function as quickly as we can that we can re-use to authenticate our users:</p>
<div class="tutorial_image"><img  src="http://nettuts.s3.amazonaws.com/Articles/009_Security/NETTUTS-SEC/mainpages/flow a - php login.gif" width="600" height="396"></div>
<h2>$_REQUEST Variables</h2>
<p>In the code above you will notice I’ve highlighted an area amber, and an area red. </p>
<p>Why did I highlight the not-so-dangerous <i>$_REQUEST</i> variables?</p>
<p>Although this doesn’t expose any real danger, what it does allow for is a lax approach when it comes to client side code. PHP has three arrays that most of us use to get our posted data from users, and more often than not we might be tempted to use <i>$_REQUEST.</i> This array conveniently gives our PHP access to the POST and GET variables, but herein lies a potential hang-up&#8230;</p>
<p>Consider the following scenario. You write your code client side to use POST requests, but you handover the project while you grab a break – and when you get back, your sidekick has written a couple of GET requests into the project. Everything runs okay – but it shouldn’t.</p>
<p>A little while later, an unsuspecting user types an external link into a comment box, and before you know it, that external site has a dozen username/password combinations in its referrer log.</p>
<p>By referencing the $_POST variables instead of $_REQUEST, we eliminate <u><strong>accidentally</strong></u> publishing any working code that might reveal a risky GET request.</p>
<p>The same principle applies to session identifiers. If you find you’re writing session variables into URLs, you’re either doing something wrong or you have a <u><strong>very good</strong></u> reason to do so.</p>
<div class="tutorial_image"><img  src="http://nettuts.s3.amazonaws.com/Articles/009_Security/NETTUTS-SEC/notepages/who spoof.gif" width="600" height="75"></div>
<h2>SQL Injection</h2>
<p>Referring again to the PHP code: the red highlighted line might have leaped out at some of you? For those who didn’t spot the problem, I’ll give you an example and from there see if something strikes you as risky&#8230;</p>
<div class="tutorial_image"><img  src="http://nettuts.s3.amazonaws.com/Articles/009_Security/NETTUTS-SEC/mainpages/flow a - sql inject.gif" width="600" height="300"></div>
<p>This image makes clear the flaw in embedding variables directly into SQL statements. Although it can’t be said exactly <i>what</i> control a malicious user could have – it is guaranteed, if you use this method to string together an SQL statement, your server is barely protected. The example above is dangerous enough on a read-only account; the powers a read/write connection have are only limited by your imagination.</p>
<p>To protect against SQL injection is actually quite easy. Let’s first look at the case of quote enclosed string variables:</p>
<p>The quickest protection is to strip the <b>enclosure</b> characters or escape them. Since PHP 4.3.0 the function <i>mysql_real_escape_string</i> has been available to cleanse incoming strings. The function takes the raw string as a single parameter and returns the string with the volatile characters escaped. <b>However</b> <i>mysql_real_escape_string</i> doesn’t escape all the characters that are valid control characters in SQL&#8230; the highlighted elements in the image below shows the techniques I use to sanitise <b>String, Number </b>and <b>Boolean</b> values.</p>
<div class="tutorial_image"><img  src="http://nettuts.s3.amazonaws.com/Articles/009_Security/NETTUTS-SEC/mainpages/flow a - sql cleaning.gif" width="600" height="849"></div>
<p>The first highlight, the line that sets <i>$string_b</i> uses a PHP function called <i>addcslashes</i>. This function has been part of PHP since version 4 and as is written in the above example, is my preferred method for SQL string health and safety.</p>
<p>A wealth of information is available in the PHP documentation, but I’ll briefly explain what <i>addcslashes</i> does and how to it differs to <i>mysql_real_escape_string</i>.</p>
<div class="tutorial_image"><img  src="http://nettuts.s3.amazonaws.com/Articles/009_Security/NETTUTS-SEC/mainpages/flow a - rep func.gif" width="600" height="140"></div>
<p>From the diagram above you can see that <i>mysql_real_escape_string</i> doesn’t add slashes to the (%) percent character.</p>
<p>The % is used in SQL <i>LIKE</i> clauses, as well as a few others. It behaves as a wildcard and <b>not</b> a literal character. So it should be escaped by a preceding backslash character in any cases where string literals make up an SQL statement.</p>
<p>The second parameter I pass to <i>addcslashes</i>, which in the image is <b>bold</b>; is the character group PHP will add slashes for. In most cases it will <u>split</u> the string you provide into <u>characters</u>, and then operate on each. It is worth noting, that this character group can also be fed a range of characters, although that is beyond the scope of this article – in the scenarios we’re discussing, we can use alphanumeric characters literally e.g. “abcd1234” and all other characters as either their C-style literal “\r\n\t”, or their ASCII index “\x0A\x0D\x09”.</p>
<div class="tutorial_image"><img src="http://nettuts.s3.amazonaws.com/Articles/009_Security/NETTUTS-SEC/notepages/note literals.gif" width="600" height="75"></div>
<p>The next highlight makes our number values safe for SQL statements.</p>
<p>This time we don’t want to escape anything, we just want to have nothing but a valid numerical value – be it an integer or floating point.</p>
<p>You might have noticed <b>line<br />
10</b>, and perhaps wondered as to the purpose. A few years ago I worked on a<br />
call centre logging system that was using <i>variable<br />
+= 0;</i> to ensure numerical values. Why this was done, I cannot honestly say&#8230;<br />
unless prior to PHP 4 that was how we did it?! Maybe somebody reading can<br />
shed some light on the subject. Other than that, if you, like I did, come<br />
across a line like that in the wild, <u>you’ll know what it’s trying to do</u>.</p>
<p>Moving forward then; <b>lines</b><br />
<b>11 </b>and <b>12</b> are all we need to prepare our numerical input values for SQL. I should say, had the input string <i>$number_i </i>contained any non-numerical characters <u>in front</u> or <u>to the left</u> of the numerical ones&#8230; our values <i>$number_a</i>, <i>$number_b</i> and <i>$number_c</i> would all <u>equals 0</u>.</p>
<p>We’ll use <i>floatval</i> to clean our input numbers; PHP only prints decimal places when they exist in the input value – so printing them into an SQL statement won’t cause any errors if no decimal was in the input. As long as our server code is safe, we can leave the more finicky validating to our client side code.</p>
<p>Before we move on to a final listing for our PHP, we’ll glance at the final <i>code</i> highlight, the Boolean boxing.</p>
<p>Like the C++ equivalent, a Boolean in PHP is really an integer. As in, True + True = Two. There are countless ways to translate an input string to a Boolean type, my personal favourite being: <i>does the lower case string contain the word true?</i></p>
<p>You each may have you own preferred methods; does the input string explicitly equal “true” or is the input string “1” etcetera&#8230; what is important is that the value coming in, whatever it might look like, is represented by a Boolean (or integer) before we use it.</p>
<div class="tutorial_image"><img  src="http://nettuts.s3.amazonaws.com/Articles/009_Security/NETTUTS-SEC/notepages/note booleans.gif" width="600" height="75"></div>
<p>My personal philosophy is simply, if X is true or false, then X is a Boolean. I’ll blissfully write all the code I might need to review later with Booleans and <b>not</b> short, int, tinyint or anything that isn’t Boolean. What happens on the metal isn’t my concern, so <u>what it looks like to a human is far more important</u>.</p>
<p>So, as with numbers and strings, our Booleans are guaranteed safe from the moment we pull them into our script. Moreover our hygienic code doesn’t need additional lines.</p>
<div class="tutorial_image"><img  src="http://nettuts.s3.amazonaws.com/Articles/009_Security/NETTUTS-SEC/notepages/who sql inject.gif" width="600" height="75"></div>
<h2>Processing HTML </h2>
<p>Now that we have our protected our SQL from injections, and we’ve made certain only a POST login can affably work with our script, we are ready to implement our review submission feature.</p>
<p>Our client wants to allow review enabled users to format their contributions as regular HTML. This would seem straightforward enough, but we also know that emails addresses are ten to the penny, and bookstore accounts are created programmatically – so in the better interests of everyone we’ll make sure <u>only the tags we say pass</u>.</p>
<p>Deciding how we check the incoming review might seem daunting. The HTML specification has a rather wholesome array of tags, many of which we’re happy to allow. </p>
<p>As longwinded the task might seem, I eagerly advise everyone – <b>choose what to allow, and never what to deny</b>. Browser and server mark-up languages <i>all</i> adhere to XML like structuring, so we can base our code on the fundamental fact that executable code must be surrounded by, or be part of, angle bracketed tags.</p>
<p>Granted, there are several ways we can achieve the same result. For this article I will describe one possible regular expression pipeline:</p>
<div class="tutorial_image"><img  src="http://nettuts.s3.amazonaws.com/Articles/009_Security/NETTUTS-SEC/mainpages/flow a - tagstrip.gif" width="600" height="260"></div>
<p>These regular expressions won’t produce a flawless output, but in the majority of cases – they should do a near elegant job.</p>
<p>Let’s take a look at the regular expression we’ll be using in our PHP. You’ll notice two arrays have been declared. <i>$safelist_review </i>and <i>$safelist_comment</i> – this is so we can use the same functions to validate reviews and later, comments:</p>
<div class="tutorial_image"><img  src="http://nettuts.s3.amazonaws.com/Articles/009_Security/NETTUTS-SEC/mainpages/flow a - regexes.gif" width="600" height="452"></div>
<p>&#8230;and here is the main function that we will call to sanitise the review and comment data:</p>
<div class="tutorial_image"><img  src="http://nettuts.s3.amazonaws.com/Articles/009_Security/NETTUTS-SEC/mainpages/flow a - regfunc.gif" width="600" height="310"></div>
<p>The input parameters, I have highlighted red and blue. <i>$input</i> is the raw data as submitted by the user and <i>$list</i> is a reference to the expression array; <i>$safelist_review </i>or <i>$safelist_comment</i> depending of course on which type of submission we wish to validate.</p>
<p>The function returns the reformatted version of the submitted data – any tags that <b>don’t</b> pass any of the regular expressions in our chosen list are converted to HTML encoded equivalents. Which in the simplest terms makes <i>&lt;</i> and <i>&gt;</i> into <i>&amp;lt;</i> and <i>&amp;gt;</i> other characters are modified too, but none of these really pose a security threat to our client or the users.</p>
<p><i>Note: The functions: cleanWhitespace and getTags <b>are</b> included in the article’s source files.</i></p>
<p>You’d be correct to assume all we have really done is helped survive the aesthetics of our site’s pages, and not done everything to protect the user’s security. There still remains a rather enormous security hole even with the SQL safe, request spoofing cured and mark-up manipulated. The JavaScript injection;</p>
<p>This particular flaw could be fixed by a few more regular expressions, and/or modification to the ones we are already using. Our anchor regular expression only allows “/&#8230;”, “h&#8230;” and “#&#8230;” values as the <i>href</i> attribute – which is really only an example of a solution. Browsers across the board understand a huge variety of <i>script visible</i> attributes, such as <i>onClick</i><i>, onLoad </i>and so forth.</p>
<p>We have in essence created a thorny problem for ourselves, we wanted to allow HTML – but now we have a near endless list of keywords to strip. There is of course, a less than perfect – but quite quickly written way to do this:</p>
<div class="tutorial_image"><img  src="http://nettuts.s3.amazonaws.com/Articles/009_Security/NETTUTS-SEC/mainpages/flow a - find replace.gif" width="600" height="251"></div>
<p>On reflection you’d be absolutely justified in asking, “Why didn’t we just use BBCode or Textile or&#8230;?”</p>
<div class="tutorial_image"><img src="http://nettuts.s3.amazonaws.com/Articles/009_Security/NETTUTS-SEC/notepages/who script.gif" width="600" height="75"></div>
<p>Myself, if I were dealing with mark-up processing, I might even go for XML walking. After all the incoming data <b>should</b> be valid XML.</p>
<p>However, this article  is not meant to teach us how to regex, how to PHP or how to write anything in one particular language. The rationale behind it simply being, don’t leave any doors ajar.</p>
<p>So let’s finish off then; with quick review of what we&#8217;ve looked at:</p>
<div class="tutorial_image"><img  src="http://nettuts.s3.amazonaws.com/Articles/009_Security/NETTUTS-SEC/mainpages/checklist.gif" width="600" height="559"></div>
<p>Although this article hasn&#8217;t equipped you with any off the  shelf project. A primary purpose of my writing was not to scare away the  designers who code, or nitpick the work of coders anywhere &#8211; but to encourage  everyone to author robust code from the off. That said, I do plan to revisit certain  elements of this article in more detail later.</p>
<p>Until then, safe coding!</p>
<h2>Sample Code</h2>
<p>You can grab the sample PHP code used in this article here</p>
<div class="tutorial_image"><a href="http://nettuts.s3.amazonaws.com/Articles/009_Security/NETTUTS-SEC/sources.zip"><br />
<img src="http://nettuts.com/wp-content/themes/nettuts/site_images/button_src_nm.jpg" alt="" /></a></div>
]]></content:encoded>
			<wfw:commentRss>http://net.tutsplus.com/tutorials/tools-and-tips/can-you-hack-your-own-site-a-look-at-some-essential-security-considerations/feed/</wfw:commentRss>
		<slash:comments>91</slash:comments>
		</item>
	</channel>
</rss>
<!--
This site's performance optimized by W3 Total Cache:

W3 Total Cache improves the user experience of your blog by caching
frequent operations, reducing the weight of various files and providing
transparent content delivery network integration.

Learn more about our WordPress Plugins: http://www.w3-edge.com/wordpress-plugins/

Page Caching using memcached
Database Caching 6/27 queries in 0.009 seconds using memcached
Content Delivery Network via 

Served from: psdtutsplus.com @ 2009-11-21 15:45:30 -->