<?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/"
	xmlns:series="http://unfoldingneurons.com/"
	>

<channel>
	<title>[speaking code]</title>
	<atom:link href="http://www.speakingcode.com/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.speakingcode.com</link>
	<description>// programming / computer science / information technology / security</description>
	<lastBuildDate>Mon, 14 May 2012 19:05:40 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.2</generator>
		<item>
		<title>Building an RSS Feed Aggregate in PHP for WordPress or Anywhere, Using fetch_feed() and SimplePie</title>
		<link>http://www.speakingcode.com/2012/05/14/building-an-rss-feed-aggregate-in-php-for-wordpress-or-anywhere-using-fetch_feed-and-simplepie/</link>
		<comments>http://www.speakingcode.com/2012/05/14/building-an-rss-feed-aggregate-in-php-for-wordpress-or-anywhere-using-fetch_feed-and-simplepie/#comments</comments>
		<pubDate>Mon, 14 May 2012 16:41:43 +0000</pubDate>
		<dc:creator>rootlicker</dc:creator>
				<category><![CDATA[HTML]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[aggregate]]></category>
		<category><![CDATA[design]]></category>
		<category><![CDATA[feed]]></category>
		<category><![CDATA[loops]]></category>
		<category><![CDATA[presentation]]></category>
		<category><![CDATA[RSS]]></category>
		<category><![CDATA[SimplePie]]></category>
		<category><![CDATA[sorting]]></category>
		<category><![CDATA[tables]]></category>

		<guid isPermaLink="false">http://www.speakingcode.com/?p=337</guid>
		<description><![CDATA[This article will cover how to pull RSS/Atom feeds into WordPress or another site using the fetch_feed() function or the [...]]]></description>
			<content:encoded><![CDATA[<p>This article will cover how to pull RSS/Atom feeds into WordPress or another site using the <a title="fetch_feed() function on WP Codex" href="http://codex.wordpress.org/Function_Reference/fetch_feed" target="_blank">fetch_feed()</a> function or the <a title="simplepie rss/atom php library" href="http://simplepie.org" target="_blank">SimplePie library</a>.  I recently started work on a new project, <a title="follow and track online and real world activism" href="tractivism.tk" target="_blank">tractivism.tk</a>, which is more or less an aggregate of RSS feeds related to activism &#8211; environmental agencies, policy watchdogs, civil rights groups, protest organizers, petitions, hacktivists, etc. For the first phase,  I simply wanted to pull feed info (url, name, etc.) from a sql table and display it neatly on a page, in an alphabetized listing.This turned out to be pretty simple in PHP, so let&#8217;s go through the process of building such an aggregate.</p>
<p>These examples use the fetch_feed() function of WordPress because I built the page they are taken from inside of the Wordpres framework. This function uses the SimplePie library, so if you&#8217;re building outside of WordPress most of the syntax will work the same with only a small bit of plugging-in.</p>
<p>First, let&#8217;s just pull a feed.</p>
<pre class="brush:php">&lt;?php
if(function_exists('fetch_feed'))
{
	include_once(ABSPATH . WPINC . '/feed.php');  // include the rss reader functionality
}
$feed = fetch_feed("http://speakingcode.com/feed"); // specify the source feed
$feed-&gt;set_cache_duration(240); //set cache rate, in this example 4 minutes (240 seconds)
$limit = $feed-&gt;get_item_quantity(5); // specify number of items to fetch, in this case 5
$items = $feed-&gt;get_items(0, $limit); // create an array of feed items
			//create a link to the feed source's site,using its title
			echo '&lt;a href="' . $feed-&gt;get_permalink() . '" title="' . $feed-&gt;get_title() . '"&gt;' . $feed-&gt;get_title() . '&lt;/a&gt;&lt;br&gt;';
			//output error msg if feed no results are present
			if ($limit == 0) echo '&lt;div&gt;The feed is either empty or unavailable.&lt;/div&gt;';
			else
			{
				//print out a list of items for the feed
				echo '&lt;ul&gt;';
				foreach($items as $item)
				{
					echo '&lt;li&gt;';
					echo '&lt;div&gt;&lt;a href="' . $item-&gt;get_permalink() . '" title="' . $item-&gt;get_title() . '"&gt;' . $item-&gt;get_title() . '...&lt;/a&gt;&lt;/div&gt;';
					echo '&lt;/li&gt;';
				}
			echo '&lt;/ul&gt;';
			}
		}
	}
}
?&gt;</pre>
<p class="brush:php">That&#8217;s simple enough &#8211; we call fetch_feed() with the url of the feed, which returns a feed object that we store in $feed. Then we have simple methods like get_items(), get_permalink(), get_title(), etc. to grab data about the feed, which we can easily display on the screen.</p>
<p class="brush:php">Now lets use some MySQL to pull feeds from a table instead of providing a hard-coded URL. We&#8217;ll use a table named &#8216;feeds&#8217; with &#8216;name&#8217; and &#8216;feed_url&#8217; columns. This will allow us to use custom names instead of being tied to the provided name of a feed, which often is lengthy or otherwise not what we want (for instance, &#8220;RSS Syndication feed for example.com&#8221; vs. &#8220;example.com&#8217;s latest&#8221;). We&#8217;ll wrap it into a loop so that we don&#8217;t have to duplicate code for each feed&#8230;</p>
<pre class="brush:php">&lt;?php
if(function_exists('fetch_feed'))
{
	include_once(ABSPATH . WPINC . '/feed.php');  // include the required file
	include_once(ABSPATH . '/config.php');  //include dbase config
}
//connect to database
mysql_connect("localhost", $username, $password) or die(mysql_error());
mysql_select_db($database) or die(mysql_error());

// Retrieve all the data from the "feeds" table
$result = mysql_query("SELECT * FROM feeds ORDER BY name") or die(mysql_error());  

while($row = mysql_fetch_array($result))
{
	$feed = fetch_feed($row['feed_url']); // specify the source feed
	$feed-&gt;set_cache_duration(240);
	$limit = $feed-&gt;get_item_quantity(5); // specify number of items
	$items = $feed-&gt;get_items(0, $limit); // create an array of items
	//title as link to feed source
	echo '&lt;h4&gt;&lt;a href="' . $feed-&gt;get_permalink() . '" title="' . $feed-&gt;get_title() . '"&gt;' . $row['name'] . '&lt;/a&gt;&lt;h4&gt;';
	if ($limit == 0) echo '&lt;div&gt;The feed is either empty or unavailable.&lt;/div&gt;';
	else
	{
		echo '&lt;ul&gt;';
		foreach($items as $item)
		{
			echo '&lt;li&gt;';
			echo '&lt;div&gt;&lt;a href="' . $item-&gt;get_permalink() . '" title="' . $item-&gt;get_title() . '"&gt;' . $item-&gt;get_title() . '&lt;/a&gt;&lt;/div&gt;';
			echo '&lt;/li&gt;';
		}
		echo '&lt;/ul&gt;';
	}
}
mysql_close($connection);
?&gt;</pre>
<p class="brush:php">Alright, nothing too difficult, just wrapping up in a little loop and dropping in some basic MySQL interactions. This will give us a nice, long list of all of our feeds and their items, but it won&#8217;t be pretty. Let&#8217;s jazz it up&#8230;</p>
<p class="brush:php">First, we will use a simple loop to create a &#8220;navigation&#8221; on the top, which will show every letter in the alphabet as a link to an anchor area within the page (&lt;a name=&#8221;something&#8221;&gt;&#8230; ;  &lt;a href=&#8221;#something&#8217;&gt;&#8230;). Then we will wrap our feed loop inside another loop, which passes through the alphabet again, to separate them into anchor sections based on the first letter of their title (alphabetical order)&#8230;</p>
<pre class="brush:php">&lt;?php
//links to each section (by alphabet)
echo '&lt;h3&gt;| ';
for ($i=65; $i&lt;90; $i++)
{
	echo '&lt;a href="#' . chr($i) . '"&gt;' . chr($i) . '&lt;/a&gt; | ';
}
echo '&lt;/h3&gt;';

if(function_exists('fetch_feed'))
{
	include_once(ABSPATH . WPINC . '/feed.php');  // include the required file
	include_once(ABSPATH . '/config.php');  //include dbase config
}
//connect to database
mysql_connect("localhost", $username, $password) or die(mysql_error());
mysql_select_db($database) or die(mysql_error());

//display entries with alphabetized breakdown
for ($i = 65; $i &lt; 90; $i++) //for each letter in alphabet
{
	$result = mysql_query("SELECT * FROM feeds ORDER BY name") or die(mysql_error());
	echo '&lt;tr&gt;&lt;td valign="top" align="left"&gt;&lt;a name="' . chr($i) . '"&gt;&lt;/a&gt;&lt;h3&gt;' . chr($i) . '&lt;/h3&gt;&lt;/td&gt;&lt;/tr&gt;';
	$position = 0;
	while($row = mysql_fetch_array($result))
	{
		if ($row['name'][0] == chr($i)) //if name of feed starts with the current letter we are in
		{
			echo '&lt;td style="padding:10px;" valign="top" align="justify"&gt;';
			$feed = fetch_feed($row['feed_url']); // specify the source feed
			$feed-&gt;set_cache_duration(240);
			$limit = $feed-&gt;get_item_quantity(5); // specify number of items
			$items = $feed-&gt;get_items(0, $limit); // create an array of items
			//title as link to feed source
			echo '&lt;h4&gt;&lt;a href="' . $feed-&gt;get_permalink() . '" title="' . $feed-&gt;get_title() . '"&gt;' . $row['name'] . '&lt;/a&gt;&lt;h4&gt;';
			if ($limit == 0) echo '&lt;div&gt;The feed is either empty or unavailable.&lt;/div&gt;';
			else
			{
				echo '&lt;ul&gt;';
				foreach($items as $item)
				{
					echo '&lt;li&gt;';
					echo '&lt;div&gt;&lt;a href="' . $item-&gt;get_permalink() . '" title="' . $item-&gt;get_title() . '"&gt;' . $item-&gt;get_title() . '...&lt;/a&gt;&lt;/div&gt;';
					echo '&lt;/li&gt;';
				}
				echo '&lt;/ul&gt;';
			}
		}
	}
}

mysql_close($connection);
?&gt;</pre>
<p class="brush:php"> Now that we have sections, we can clean them up. Using a variable as a counter, we can use <em>modulo n</em> to divide sections into n columns. We&#8217;ll declare a table outside of the loop, which will encompass all of the feeds. We&#8217;ll open a table row with the first item, and for every n items, we will close a table row and declare a new one. After we loop through the elements, we&#8217;ll make sure to close the last item if it wasn&#8217;t the n&#8217;th in its row, and close the table. In addition, we will use the substr() function (substring) to truncate the titles of feed items so that we get a nice uniform look.</p>
<p class="brush:php">Before I show that, let&#8217;s do one more modification. A common source of active feeds is Twitter, but we like to denote those feeds with # and @ at the front of the name, per the Twitter standard. We will modify our &#8220;matching character&#8221; condition in the if-statement by using this rule: if (first letter is # (hashtag) or @  (at-symbol) AND second letter is the current character) OR (first letter is current character) then display it in this section. Here&#8217;s how it all looks, using a 3-column example:</p>
<pre class="brush:php">&lt;?php
if(function_exists('fetch_feed'))
{
	include_once(ABSPATH . WPINC . '/feed.php');  // include the required file
	include_once(ABSPATH . '/config.php');  //include dbase config
}

//connect to database
mysql_connect("localhost", $username, $password) or die(mysql_error());
mysql_select_db($database) or die(mysql_error());

//links to each section (by alphabet)
echo '&lt;h3&gt;| ';
for ($i=65; $i&lt;90; $i++)
{
	echo '&lt;a href="#' . chr($i) . '"&gt;' . chr($i) . '&lt;/a&gt; | ';
}
echo '&lt;/h3&gt;';
//open table
echo '&lt;table&gt;';
//display entries with alphabetized breakdown
for ($i = 65; $i &lt; 90; $i++) //for each letter in alphabet
{
	$result = mysql_query("SELECT * FROM feeds ORDER BY name") or die(mysql_error());
	echo '&lt;tr&gt;&lt;td valign="top" align="left"&gt;&lt;a name="' . chr($i) . '"&gt;&lt;/a&gt;&lt;h3&gt;' . chr($i) . '&lt;/h3&gt;&lt;/td&gt;&lt;/tr&gt;';
	$position = 0;
	while($row = mysql_fetch_array($result))
	{
		//if first letter matches current char, or if the first letter is #/@ and second letter matches current char
		if ( ( ($row['name'][0] == "#" || $row['name'][0] == "@") &amp;&amp; strcasecmp($row['name'][1], chr($i)) == 0 ) || (strcasecmp($row['name'][0], chr($i)) == 0) )
		{
			if (($position % 3) == 0) echo '&lt;tr&gt;';
			echo '&lt;td style="padding:10px;" valign="top" align="justify"&gt;';
			$feed = fetch_feed($row['feed_url']); // specify the source feed
			$feed-&gt;set_cache_duration(240);
			$limit = $feed-&gt;get_item_quantity(5); // specify number of items
			$items = $feed-&gt;get_items(0, $limit); // create an array of items
			//title as link to feed source
			echo '&lt;h4&gt;&lt;a href="' . $feed-&gt;get_permalink() . '" title="' . $feed-&gt;get_title() . '"&gt;' . $row['name'] . '&lt;/a&gt;&lt;h4&gt;';
			if ($limit == 0) echo '&lt;div&gt;The feed is either empty or unavailable.&lt;/div&gt;';
			else
			{
				echo '&lt;ul&gt;';
				foreach($items as $item)
				{
					echo '&lt;li&gt;';
					echo '&lt;div&gt;&lt;a href="' . $item-&gt;get_permalink() . '" title="' . $item-&gt;get_title() . '"&gt;' . substr($item-&gt;get_title(), 0, 60) . '...&lt;/a&gt;&lt;/div&gt;';
					echo '&lt;/li&gt;';
				}
				echo '&lt;/ul&gt;';
			}
			echo '&lt;/td&gt;';
			if (($position % 3) == 2) echo '&lt;/tr&gt;'; //close the row after every three elements
			$position++;
		}
	}
	if (!(($position % 3) == 0)) echo '&lt;/tr&gt;'; //close row after final element if it wasn't the 3rd in its row.
}
echo '&lt;/table&gt;';
mysql_close($connection);
?&gt;</pre>
<p class="brush:php">There ya go. With hefty yet straightforward pair of nested loops, we get a nice, clean RSS aggregate sorted alphabetically, which handles twitter-esque hash tags and @ signs. This makes a good starting point for all sorts of customization&#8230; enjoy!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.speakingcode.com/2012/05/14/building-an-rss-feed-aggregate-in-php-for-wordpress-or-anywhere-using-fetch_feed-and-simplepie/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Introduction to SEO (Search Engine Optimization) and Online Marketing</title>
		<link>http://www.speakingcode.com/2012/05/08/introduction-to-seo-search-engine-optimization-and-online-marketing/</link>
		<comments>http://www.speakingcode.com/2012/05/08/introduction-to-seo-search-engine-optimization-and-online-marketing/#comments</comments>
		<pubDate>Tue, 08 May 2012 15:14:46 +0000</pubDate>
		<dc:creator>rootlicker</dc:creator>
				<category><![CDATA[HTML]]></category>
		<category><![CDATA[Tutorials]]></category>
		<category><![CDATA[AdWords]]></category>
		<category><![CDATA[back-links]]></category>
		<category><![CDATA[CMS]]></category>
		<category><![CDATA[Drupal]]></category>
		<category><![CDATA[google]]></category>
		<category><![CDATA[Joomla]]></category>
		<category><![CDATA[keywords]]></category>
		<category><![CDATA[marketing]]></category>
		<category><![CDATA[search engine optimization]]></category>
		<category><![CDATA[SEO]]></category>
		<category><![CDATA[traffic]]></category>
		<category><![CDATA[web]]></category>
		<category><![CDATA[WordPress]]></category>

		<guid isPermaLink="false">http://www.speakingcode.com/?p=325</guid>
		<description><![CDATA[Search Engine optimization, or SEO, is the art and skill of boosting a website&#8217;s ranking in search engine results, i.e. [...]]]></description>
			<content:encoded><![CDATA[<p style="text-align: justify;">Search Engine optimization, or SEO, is the art and skill of boosting a website&#8217;s ranking in search engine results, i.e. how high up (or how far down) on the list of results it appears when a particular search term (keyword) is given into a search engine such as Google. Most people online discover new content or find what they are looking for using search engines, so if you want your site to be seen by people who are interested in the stuff your site is about, instead of your competitors, SEO is critical. If you&#8217;re not worried about your site being discovered by people that aren&#8217;t explicitly looking for your site, then you can stop reading now (and probably get ready for your online venture to fail, unless you&#8217;re a giant, well-known brand).</p>
<p style="text-align: justify;">Google is the most used search engine, so naturally, optimizing for Google is the best bet. Unfortunately, Google&#8217;s engine (called Panda) is always being tweaked and modified to make it &#8220;better&#8221;, prevent abuse, etc., so SEO is an on-going game. Some particular SEO voodoo will lose its glitttering value as changes are made, but in general, a good SEO strategy will remain valid for a long time.</p>
<p style="text-align: justify;">So how does Google rank pages? Very few people know exactly how for certain, but its sort of known at a high level. Their servers crawl the web and keep a record of all the words on every page crawled. Additionally, for every page, the engine keeps track of how many links to that page it finds on other pages. The general idea is that the more people decide to link to a particular page, the more useful its content probably is. When a user searches for a term, it pulls every page that contains that term (and probably variations of the term and closely-related terms) and then orders them based on several criteria, such as strength and frequency of match (how often does the keyword appear in content of the page?), estimated relevance, number of backlinks, quality of content (is it gibberish, is it unqiue or duplicated from elsewhere, etc.) and other factors. To what extent each factor matters is not certain and it changes pretty often. Some criteria (for instance meta-keywords, at the time of this writing) are overlooked completely, and others are hard to describe (such as statistical pattern matching on how &#8220;good&#8221; a site is based on user-driven seed data). I suspect Google also looks at your cookies and tries to order results based on &#8220;personalized matches&#8221;.</p>
<p style="text-align: justify;">The complexity of SEO and the ever-changing rules to follow make it daunting, but there are good approaches that keep things simple and maximize impact for the least effort. Good SEO and marketing is built into a site from the ground up, so we&#8217;ll talk about SEO in phases. It isn&#8217;t necessary for each phase to be done in a certain order or for each to be done at all, but for this article we&#8217;ll assume starting from the beginning on a new SEO-optimized site.</p>
<h3 style="text-align: justify;">Phase 1 &#8211; Keywords</h3>
<p style="text-align: justify;">SEO is all about keywords: choosing the right keywords to target and targetting them in the right way, in every way feasible. You have an idea for a great new website or web business. Awesome. First things first, you need to find out the best keywords around the domain the website targets (not .com domain, business domain!). Use Google&#8217;s AdWords tools (free) to find which terms (relevant to your site) are the most searched for. Suppose you&#8217;re planning to launch a site to sell your home-grown coffee beans. You might check &#8220;buy coffee&#8221;, &#8220;purchase coffee&#8221;, &#8220;home grown coffee&#8221;, &#8220;buy coffee beans&#8221;, &#8220;order coffee&#8221;, &#8220;order coffee beans&#8221;, etc. Look for the search terms (sometimes they are phrases, not just one word) that are relevant, have the highest number of searches and the lowest amount of competition (when possible). AdWords tools will suggest similar terms based on the ones you check, so utilize those features.</p>
<p style="text-align: justify;">If you&#8217;re targetting a particular area or region, you should include it in the terms you check, for instance &#8220;buy coffee in Memphis&#8221;, &#8220;Memphis coffee&#8221;, &#8220;Memphis coffee beans&#8221;, and so forth. Get a list of the 5 to 7 strongest relevant search terms; we&#8217;ll be baking them into every part of the site we can very soon. In a competitive industry (which most are in the online world), there will be other sites targeting the same keywords and phrases. You can use tools like those on spyfu.com to research your successful competitor&#8217;s targeted keywords and do other analysis to succeed the same way they do.</p>
<h3 style="text-align: justify;">Phase 2 &#8211; Branding</h3>
<p style="text-align: justify;">Choose a good name for your site. What&#8217;s a good name? One that is short, easy to remember, easy to spell, catchy, and with availability. If you can include one or more of your targetted keywords, even better! You&#8217;d be surprised how much more effective a search-optimized name like &#8220;Cheap Coffee Deals&#8221; or &#8220;Buy Coffee Fast&#8221; might be over a cute pun like &#8220;Java Jam&#8221; or &#8220;Beans-n-Things&#8221; (assuming &#8216;cheap coffee deals&#8217; or &#8216;buy coffee fast&#8217; are strong keywords). And by availability, I mean not just available as a brand name, but in .com form, and on all social networks and user sites. If the .com form of your name is already taken, choose a new name. Sometimes you can do &#8220;domain hacks&#8221; like del.icio.us and bit.ly, but in general most people remember and type in &#8220;whatever.com&#8221; when they are looking for a brand&#8217;s site. You&#8217;ll want to set up accounts on every social network, link baord, and content-share you can think of &#8211; Twitter, Facebook, Delicious, Reddit, Tumblr, StumbleUpon, Google+, YouTube, Vimeo, etc. &#8211; and use the same name for all of &#8216;em. Suppose for our made-up coffee example we decided the name &#8220;Memphis Coffee&#8221;. We want memphiscoffee.com, twitter.com/memphiscoffee, facebook.com/memphiscoffee, memphiscoffee.tumblr.com, youtube.com/memphiscoffee, and so on. The availability of words gets less and less with every passing second, so sometimes it&#8217;s hard to have a consistent name across all channels&#8230; do your best, but don&#8217;t get too hung up if you have to use variations on some channels &#8211; it&#8217;s impossible to avoid sometimes. Don&#8217;t spend too much time &#8211; phase 1 and 2 can be done in a day (and often are, even for big successful startups) &#8211; getting to market is more important than having the &#8220;perfect&#8221; catchy name.</p>
<h3 style="text-align: justify;">Phase 3 &#8211; Optimize for Keywords</h3>
<p style="text-align: justify;">We have our 5 or so strongest terms, and we have a brand name with a matching .com and account names on the popular social networks, hopefully with some keywords included in it. We need to pump our keywords/phrases into our site in every way possible, as we build it &#8211; in the content, in meta tags and descriptions, in page titles, in filenames, in urls, in HTML attributes, in image captions, etc. What, that sounds difficult to maintain? Are you using a CMS (content management system) like WordPress or Drupal to build your site? If not, you probably should consider it (unless you&#8217;re going to be dumping big dollars into a custom built site and lots of advertising to make up for the lack of SEO-friendliness). Also, we want to keep our titles and descriptions down to 140 characters or less. Most search engines only read and display the first 140 or so characters; we want to catch both the search engine and the user reading results in one punch, so keep them short and include keywords. Suppose our prime keywords are &#8220;buy coffee&#8221;, &#8220;order coffee&#8221;, &#8220;buy home grown coffee&#8221;, &#8220;memphis grown coffee&#8221;, and &#8220;order coffee beans online&#8221; A snippet of very basic SEO-optimized HTML might look like:</p>
<pre class="brush:xml">&lt;html&gt;
&lt;head&gt;
&lt;title&gt;Buy home grown coffee beans from Memphis Coffee. Order coffee, buy home grown coffee, Memphis grown coffee, order coffee beans online&lt;/title&gt;
&lt;/head&gt;
&lt;body&gt;
&lt;a
  href="memphiscoffee.com"
  id="banner-link_mempis-coffee_buy-coffee-order-coffee-buy-home-grown-coffee-memphis-grown-coffee-order-coffee-online"
  title="Buy home grown coffee beans from Memphis Coffee. buy coffee, order coffee, buy home grown coffee, memphis grown coffee, order coffee beans online"&gt;
&lt;img
  src="banner_memphis-coffee_buy-coffee-order-coffee-buy-home-grown-coffee-memphis-grown-coffee-order-coffee-online.png"
  alt="Buy home grown coffee beans from Memphis Coffee. buy coffee, order coffee, buy home grown coffee, memphis grown coffee, order coffee beans online"
  title="Buy home grown coffee beans from Memphis Coffee. buy coffee, order coffee, buy home grown coffee, memphis grown coffee, order coffee beans online"
  id="banner_mempis-coffee_buy-coffee-order-coffee-buy-home-grown-coffee-memphis-grown-coffee-order-coffee-online"&gt;
&lt;/a&gt;
&lt;br&gt;
&lt;br&gt;
&lt;p&gt;
Welcome to Memphis Coffee, where you can buy and order home grown coffee and Memphis grown coffee, order coffee beans, and more.
&lt;a
  href="memphiscoffee.com/store_mempis-coffee_buy-coffee-order-coffee-buy-home-grown-coffee-memphis-grown-coffee-order-coffee-online.php"
  id="store-link_mempis-coffee_buy-coffee-order-coffee-buy-home-grown-coffee-memphis-grown-coffee-order-coffee-online"
  title="View the Memphis Coffee store. Buy coffee, order coffee, buy home grown coffee, memphis grown coffee, order coffee beans online"&gt;
See our store&lt;/a&gt; to check out our huge variety of coffee beans as well as fresh-ground home grown coffee...
&lt;/p&gt;
&lt;/body&gt;
&lt;/html&gt;</pre>
<p style="text-align: justify;">Now of course this example is a bit over-the-top in that the actual content is lacking and has little substance other than the overhaul of SEO, and the tacky overkill of keywords in the text. Consider it exaggeration for the sake of emphasis, but don&#8217;t be fooled &#8211; having the keywords in all those attributes and titles is the goal. Inject them everywhere. Be sure to balance it with lots of actual meaningful content (and be subtle in how you sneak your top phrases in &#8211; a common trend is to put them in the page/post name, in the first paragraph, and in the last paragraph). Speaking of content&#8230;</p>
<h3 style="text-align: justify;">Phase 4 &#8211; Content, Content, Content</h3>
<p style="text-align: justify;">In the web world, content is king, and SEO is no exception. Without good content (and at least a decent presentation) most people won&#8217;t read your site, they won&#8217;t come back to your site, they won&#8217;t recommend it or share it, and they&#8217;ll likely be weary of buying any products. Search engines share this sentiment, and favor sites with lots of content that is filled with words and updated regularly. How regularly? Most SEO experts seem to agree that you should strive to update daily; at the very very minimum, a couple of times a week. This phase could easily be called &#8220;UPDATE UPDATE UPDATE!&#8221; In terms of SEO, it&#8217;s not about changing your design and layout, reworking your CSS or any of that.. it&#8217;s about adding content, and in that meaty content &#8211; inject your prime keywords.</p>
<p style="text-align: justify;">Blogging is a wonderful way to keep your content growing and your target audience finding you. Some benefits of blogging:</p>
<ul>
<li>Each blog post is an update. Google likes updates. It&#8217;s like telling the engine, &#8220;Come back and look at me, I have something new to share with the world!&#8221;</li>
<li>Each blog post adds content. Google likes lots of content. The more you feed the hungry monster, the better off you&#8217;ll be. Not to mention, it&#8217;s easy to cleverly sneak some or all of your targeted  keywords into each post without being obnoxious.</li>
<li>Blog articles are typically dated and most blog platforms support organizing your articles by date (among other topology). This is a great way to present time-sensitive information (like a sales announcement) in a place where it can stay forever. Imagine updating sales or news on a static page &#8211; every time something expires, you&#8217;d have to take it down and put something else in, losing all that valuable content and handling tedious changes.</li>
<li>Users like blogs. Marketing, especially online, is all about connected-ness these days. Users like to comment on articles and share the latest news with their friends (which helps generate back-links to your site). They like to have dialogue with people from the company/brand/service, one in which they have input on the direction of the company. They like to see updates from the company, as it gives the impression that the company is alive and active and engaging&#8230; all this helps build brand loyalty, which is very important for businesses.</li>
<li>Each article adds pages. Most blog systems (like WordPress) dynamically generate index pages, archive pages, category listings, etc. for the articles, and each article amounts to at least 1 (if not several) pages being created or modified with the contents of the article. Google likes big sites with lots of pages, and it really likes when there&#8217;s a nice web of internal linking among pages on a site&#8230; content and links are like air and water for the search engines, so this means SEO feeding frenzy.</li>
</ul>
<p style="text-align: justify;">It gets clear that using a CMS to help manage files, pages, links, indexes, and so on becomes more than necessary. Copying and pasting is a useful tool as well, but imagine doing this kind of &#8220;keyword injection&#8221; in several pages on a regular basis, updating indexes, updating internal links, etc. etc. etc. by hand &#8211; it will make your head spin and you&#8217;ll die of cranial explosion. So find a good CMS like WordPress (my preference), SquareSpace, Joomla, or Drupal and master it &#8211; you&#8217;ll never look back.</p>
<h3 style="text-align: justify;">Phase 5 &#8211; Backlinks and Sharing</h3>
<p style="text-align: justify;">This is the hardest part of SEO because, ultimately, it depends on other people putting links to your site somewhere. But you can take steps to encourage and streamline the process so that people are more inclined to share your site to others.</p>
<p style="text-align: justify;">Remember all those social network accounts you setup in the branding phase? I hope you&#8217;ve been steadily adding friends and engaging the communities. Every time you post a new article on your blog, add a new page, a new section, new feature, whatever &#8211; post a link on every single social network you have. Ideally people will like what they see and repost it on their account (Re-tweet, Share, +1, Like, Digg, Thumbs Up, etc.) The 140 character titles and descriptions come handy here, because many social networks limit the length of posts. Be sure to follow the proper etiquette of each individual service &#8211; don&#8217;t be a spammer or appear only concerned about driving traffic for yourself, as people catch on and generally hate it. Engage genuinely in discussions about topics relevant to your business and people will credit you as a knowlegeable player in that field.</p>
<p style="text-align: justify;">In addition to using social channels to spread the word about your updates (which builds back-links and encourages others to do so for you), you can use tools to encourage users to share your content from within your site. Most social networks have a general URL you can use to automate sharing, like www.whatevernetwork.com/share.php?name=CoolSite&amp;url=memphiscoffee.com. Put links to those on every page and post so that your users can just click one link and automatically share it on the corresponding network without hassle. WordPress (and probably other blog-based CMS platforms) have plugins that will automatically do this for dozens of social networks on every single page and post on your site. Use them.</p>
<p style="text-align: justify;">There are link building services online that will submit links to your site on many directories and sites. These range from free to costly and from very legitimate to extremely unethical (and sometimes even criminal). Several sites exist as link directories and indexes, link trading networks, etc. and it&#8217;s good to be on them, though often not very effective. On the other end are tools and services that spam links on every comment box they can find on the web, or generate tons of zero-content &#8220;link farm&#8221; sites that exist soley to build backlinks to a particular site. Google&#8217;s Panda engine is made to spot link farms and will even derank pages that are link farmed. Not to mention, a lot of the shady link building services are ran by con artists and criminals of very questionable character; not all, but many. So be careful in that area.</p>
<p style="text-align: justify;">Wasn&#8217;t that simple? That&#8217;s it, you&#8217;re done. NOT! The last component to a good SEO strategy is continuity. Google changes their engine in various ways pretty regularly, and most other search engines follow their model. SEO requires regular maintenance and investigation into the latest tricks of the trade, the latest trends in your market, etc. Persistence is the key. If your site has quality content that is updated regularly, and if you engage the online world in several social channels, you&#8217;ll do alright. Not every good site or service goes viral, but most of the decent ones, following these basic optimization guidelines, will catch on and get good traffic from search engines before long.</p>
<p style="text-align: justify;">Bear in mind, these are just some basics of SEO, which is a pretty extensive field of ongoing research and development, shifting approaches, endless tools, and myriad details. You can get books and find sites online to go deeper into the subject, these are just the basics. Good luck!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.speakingcode.com/2012/05/08/introduction-to-seo-search-engine-optimization-and-online-marketing/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Introducing GeekBlog.tv</title>
		<link>http://www.speakingcode.com/2012/05/07/introducing-geekblog-tv/</link>
		<comments>http://www.speakingcode.com/2012/05/07/introducing-geekblog-tv/#comments</comments>
		<pubDate>Mon, 07 May 2012 18:04:52 +0000</pubDate>
		<dc:creator>rootlicker</dc:creator>
				<category><![CDATA[Rants]]></category>

		<guid isPermaLink="false">http://www.speakingcode.com/?p=319</guid>
		<description><![CDATA[A friend of mine recently started a new web venture, GeekBlog.tv, an obviously tech-centric blog site with focus on information [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.speakingcode.com/wp-content/uploads/2012/05/geekblog-tv.jpg"><img class="alignleft size-medium wp-image-320" title="geekblog-tv" src="http://www.speakingcode.com/wp-content/uploads/2012/05/geekblog-tv-300x42.jpg" alt="" width="300" height="42" /></a>A friend of mine recently started a new web venture, <a title="geekblog.tv" href="http://geekblog.tv">GeekBlog.tv</a>, an obviously tech-centric blog site with focus on information security, hacking (not the criminal kind,the  &#8217;cool tricks&#8217; kind), and general tech wizardry. What makes it really super awesome, though, is the fact that I&#8217;m a senior editor for the site, which automagically boosts its incredibility rating by a significant 1.37%</p>
<p>Seriously, though, what makes the site cool is the focus on video content. Whether it&#8217; a tutorial, a demonstration, whatever, James (the founder) is serious about getting an <strong>informative</strong> video up on the site every single day, along with regular articles steadily pouring in. I&#8217;ve written a couple myself, including one on <a title="Run Android Apps on your Windows PC with BlueStacks" href="http://geekblog.tv/296" target="_blank">how to run Andriod apps on Windows</a> and another about <a title="John McAffee arrested for guns and weapons charges" href="http://geekblog.tv/532" target="_blank">John McAffee getting arrested for gun and drugs charges</a>. So in short, GeekBlog.tv is an awesome site with focus on fresh, relevant, QUALITY content. No fluff, no overdone SEO padding, no swimming through rivers of generic statements to find the meat&#8230; so check it out and learn some good tips and info. While you&#8217;re at it, follow <a title="@geekblogtv" href="http://twitter.com/#!/geekblogtv" target="_blank">@geekblogtv</a> on twitter!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.speakingcode.com/2012/05/07/introducing-geekblog-tv/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Pressure of the Masses &#8211; Fact or Fiction? The Future of Online Activism</title>
		<link>http://www.speakingcode.com/2012/04/13/pressure-of-the-masses-fact-or-fiction-the-future-of-online-activism/</link>
		<comments>http://www.speakingcode.com/2012/04/13/pressure-of-the-masses-fact-or-fiction-the-future-of-online-activism/#comments</comments>
		<pubDate>Fri, 13 Apr 2012 19:36:58 +0000</pubDate>
		<dc:creator>rootlicker</dc:creator>
				<category><![CDATA[Rants]]></category>
		<category><![CDATA[activism]]></category>
		<category><![CDATA[freedom]]></category>
		<category><![CDATA[online campaigns]]></category>
		<category><![CDATA[petition]]></category>
		<category><![CDATA[privacy]]></category>
		<category><![CDATA[protest]]></category>

		<guid isPermaLink="false">http://www.speakingcode.com/?p=303</guid>
		<description><![CDATA[In recent months, viral online campaigns have had tremendous results in raising public awareness, putting pressure on companies and governments, [...]]]></description>
			<content:encoded><![CDATA[<div id="attachment_310" class="wp-caption alignleft" style="width: 310px"><a href="http://www.speakingcode.com/wp-content/uploads/2012/04/speakingcode.com-privacy-on-twitter.jpg"><img class="size-medium wp-image-310" title="speakingcode.com-online-activism" src="http://www.speakingcode.com/wp-content/uploads/2012/04/speakingcode.com-privacy-on-twitter-300x200.jpg" alt="online activism speakingcode.com" width="300" height="200" /></a><p class="wp-caption-text">Good ole technology makes spreading a cause... too easy?</p></div>
<p style="text-align: justify;">In recent months, viral online campaigns have had tremendous results in raising public awareness, putting pressure on companies and governments, and effecting actual change in policy and practices. Besides getting the word out on social networks, new ways of joining a cause are emerging. Online activism sites are springing up left and right, some dedicated to specific agendas, others generalized for all sorts of issues. Start or sign a petition. Orchestrate an email campaign. Coordinate a protest. Gather resources&#8230;  Fighting for a cause is no doubt becoming easier to carry out, but <em>as online activism becomes trendy, its efficacy may suffer</em>&#8230;</p>
<p style="text-align: justify;">Recent campaigns range from stopping legislation such as SOPA/PIPA, pressuring companies like Walmart and Target to treat employees better, and even changing outcomes of police investigations such as the Treyvon Martin case. A number of campaigns, like the ones mentioned, seem to be successful in achieving their intended goal, but their success may have largely depended on social circumstances, circumstances which are quickly changing.</p>
<h3 style="text-align: justify;">The Opposite of Unity is Division</h3>
<p style="text-align: justify;">Let&#8217;s consider the &#8220;competition&#8221; angle. As multiple services compete to be <em>the</em> place for online activism, the number of <em>active</em> users on any given service will decrease. Some will go here, some will go there, some will go elsewhere. Although seemingly minor, the big stick wielded by online activism is the power of sheer volume and the ability to demonstrate that masses of people feel a certain way around an issue in a hard-evidenced, factual number. While politicians and decisions makers surely make efforts to keep their ears open to the buzz of &#8220;what&#8217;s going on in the public&#8221;, their decisions are much more influenced directly by <em>number</em>s which show how their constituents, customers, etc. actually side. One source saying &#8220;X million actual people sided this way&#8221; has a bigger impact than few sources saying &#8220;X thousand people sided this way&#8221;.</p>
<p style="text-align: justify;">In terms of petitions, it becomes harder (though not impossible by any means) for any one petition to grow to impressive size when there are multiple petitions on the same issue. It doesn&#8217;t mean they don&#8217;t have any value or weight, but consider this: Senator A gets a petition on some issue with 10,000 signatures. Maybe it catches his attention, but from a senator&#8217;s point of view 10,000 online signatures probably doesn&#8217;t seem significant. &#8220;How many are valid? How many are registered voters? How many are my own constituents? Is the issue that big?&#8221; Senators B, C, D, and E get petitions on the same issue with another 10,000 signatures each, and have the same sentiment. But what happens when a senator gets a petition with 50,000 signatures? &#8220;Maybe I better call Bob, Bill, and John and talk about this.&#8221; The impact of a <strong>huge</strong> number of signatures going to one &#8220;bigwig&#8221; can be greater than several disparate petitions reaching several bigwigs.</p>
<h3 style="text-align: justify;">Ongoing disruption is noise, and noise gets tuned out.</h3>
<div id="attachment_311" class="wp-caption alignright" style="width: 310px"><a href="http://www.speakingcode.com/wp-content/uploads/2012/04/speakingcode.com-protest.jpg"><img class="size-medium wp-image-311 " title="budget_bill_protest11_4092" src="http://www.speakingcode.com/wp-content/uploads/2012/04/speakingcode.com-protest-300x199.jpg" alt="speakingcode.com online activism" width="300" height="199" /></a><p class="wp-caption-text">Take to the streets! Our voices must be heard.</p></div>
<p style="text-align: justify;">Another angle of concern is &#8220;crowding&#8221; &#8211; things don&#8217;t stick out as much when everyone does it. As activism becomes trendy, more issues get pushed. More campaigns, more petitions, more emails, more tweets.. it becomes harder for important issues to gain momentum when they are overshadowed by myriad issues of lesser significance. We&#8217;ve all gotten the endless followups from change.org and the like, asking us to join one cause after the other. Soon enough, we ignore them, or a filter sends each and everyone to the trash bin upon arrival.</p>
<p style="text-align: justify;">Crowding can also have an adverse effect on the reactions that campaigns get from the people they target. Campaigns start to get common and lose the shock value. Issues degrade into bitch-sessions about return fees, inconvenient hours, costs, and other concerns which, although valid, probably don&#8217;t demand national attention and outcry. Frankly, it turns into annoyance at best. Think about all the customer-feedback channels: phone numbers, emails, comment boxes, etc. that get flooded with so much garbage that companies hardly bother reviewing them. Those petition letters that made Senator John Doe panic and say &#8220;Oh crap!&#8221; start going straight to the trash bin as well.  They stop taking the activism AND the activists seriously. They question whether these people will really take action, or are they content with signing one &#8220;spam cause&#8221; after the next.</p>
<div id="attachment_309" class="wp-caption alignleft" style="width: 310px"><a href="http://www.speakingcode.com/wp-content/uploads/2012/04/speakingcode.com-Mail.jpg"><img class="size-medium wp-image-309" title="200567125-001" src="http://www.speakingcode.com/wp-content/uploads/2012/04/speakingcode.com-Mail-300x225.jpg" alt="speakingcode.com online activism" width="300" height="225" /></a><p class="wp-caption-text">It&#39;s hard to ignore this every day.</p></div>
<p style="text-align: justify;">Perhaps activism is becoming <em>too</em> easy. What can we, the people, do to prevent a fruitless convolution from becoming the status-quo? That&#8217;s difficult to say, but there may be a few easy-to-follow guidelines to help our protests and campaigns.</p>
<ul>
<li><strong>Limit the number of causes</strong> we try to put out to the masses through online campaigns &#8211; keep the channels clear for the stuff that&#8217;s significant, like real threats to our freedoms/rights, humanitarian abuses, and scams and malpractice which could tremendously harm society and the public.</li>
<li><strong>Send paper letters</strong>. It&#8217;s just as easy to delete an e-petition with a million signatures as it is to delete an offer for free pharmaceuticals (well, maybe that&#8217;s difficult for some people), but it&#8217;s not so easy to get rid of a million paper envelopes pouring into the mailbox. Not only do tangible materials have a physical bearing, but the time and effort it takes to write, print, envelope, stamp and send a paper letter (though miniscule) is typically more appreciated by public officials, public relations reps, and upper management. Not to mention, it&#8217;s revenue for the precious postal system, which is struggling to stay afloat these days.</li>
<li><strong>Take real action</strong>. Make phone calls. Put up fliers and posters. Deliver informative handouts and pamphlets to people.  Take to the streets for peaceful demonstrations. The power of a massively aligned online community is slim in comparison to an active populace. Use the Internet to spread the word and raise awareness; don&#8217;t pat yourself on the back as an activist for re-tweeting and clicking a few buttons.</li>
</ul>
<p style="text-align: justify;">We are in a precious period where the masses are once again being recognized by the elites as a dynamic force which is capable of organizing, aligning, and demanding change. It is absolutely crucial, while we have their attention, to show that we can foster this momentum into productive action. Good luck, comrades!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.speakingcode.com/2012/04/13/pressure-of-the-masses-fact-or-fiction-the-future-of-online-activism/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Using Tor to Anonymize Your Traffic (and setting up Tor in Arch Linux)</title>
		<link>http://www.speakingcode.com/2012/04/13/using-tor-to-anonymize-your-traffic/</link>
		<comments>http://www.speakingcode.com/2012/04/13/using-tor-to-anonymize-your-traffic/#comments</comments>
		<pubDate>Fri, 13 Apr 2012 08:04:26 +0000</pubDate>
		<dc:creator>rootlicker</dc:creator>
				<category><![CDATA[Security]]></category>
		<category><![CDATA[Tutorials]]></category>
		<category><![CDATA[anonymity]]></category>
		<category><![CDATA[arch linux]]></category>
		<category><![CDATA[encryption]]></category>
		<category><![CDATA[gpg]]></category>
		<category><![CDATA[https]]></category>
		<category><![CDATA[onion routing]]></category>
		<category><![CDATA[privacy]]></category>
		<category><![CDATA[proxy]]></category>
		<category><![CDATA[security]]></category>
		<category><![CDATA[tor]]></category>
		<category><![CDATA[transport layer]]></category>

		<guid isPermaLink="false">http://www.speakingcode.com/?p=254</guid>
		<description><![CDATA[There are many, many aspects of security, and the only way to be highly secure is to always be learning, [...]]]></description>
			<content:encoded><![CDATA[<p style="text-align: justify;">There are many, many aspects of security, and the only way to be highly secure is to always be learning, tweaking, watching, taking precautions, applying updates, thinking out side of the box, etc. etc. etc. Security holes can be hidden anywhere, from the deeply complex software exploit in some application you use, to the seemingly junk mail you threw in the wastebin.</p>
<p style="text-align: justify;">This article is focused on one particular, narrow, but highly-important aspect of security: anonymizing your Internet traffic. Really, that&#8217;s a broad topic in and of itself, thus the narrow indicates that we probably aren&#8217;t covering everything. Don&#8217;t go acting stupid and thinking these steps make you invincible!</p>
<p style="text-align: justify;">Among others, Arch is a Linux distro I love. There are many distros, with their pros and cons, their ups and downs, their quirks, their special purposes, and so forth. I&#8217;m definitely not saying Arch is the end-all of distros, but I find it to be quite excellent as a general-purpose, day-to-day desktop dsitro. So this tutorial uses commands based on the Arch package manager, pacman. If you don&#8217;t use Arch, compile from source or rtfm on your distro and use whatever package manager and configurations it has.</p>
<p style="text-align: justify;">First, let&#8217;s create a fresh user. This gives us a fresh start in terms of user settings, and a sort of silo to play and experiment with privacy-intensive configurations without affecting our general-use user.</p>
<pre># useradd -m -g users -G audio,lp,optical,storage,video,wheel,games,power,scanner -s /bin/bash someuser</pre>
<p style="text-align: justify;">Now we want to add the wheel group to the sudoers file so that our new user can perform root tasks using sudo when needed. Type in:</p>
<pre># EDITOR="nano" visudo</pre>
<p style="text-align: justify;">and add the following line:</p>
<pre>%wheel ALL=(ALL)</pre>
<p style="text-align: justify;">Great. Now our new user, &#8220;someuser&#8221; in this case, can perform commands as root using sudo. Lets get started.</p>
<p style="text-align: justify;">First, we want to install tor. Tor is an onion-routing based proxy used to anonymize your browsing. Basically, each person running tor is also a node on the tor network. Your tor client connects to a central server, gets a list of a couple of random nodes, and routes your traffic through those nodes. Each node has a public key, so your client encrypts your data multiple times, using each node&#8217;s key, in reverse order. So your data is encrypted for the last node first, then the second node, and finally encrypted for the first node. Then, each node decrypts its layer (thus <em>onion</em> routing) before passing your data to the next node. Once the data reaches the last node, called the &#8220;exit node&#8221;, it is back in its original, unencrypted form.</p>
<p style="text-align: justify;">At this point, it&#8217;s quite difficult for anyone to determine where the data originated, unless of course the data itself contains information about the originator. End-to-end encryption is used between each hop for added protection, but again the data is back in its original form when leaving the last hop of the tor network and going back out to the public web. Use https and other end-to-end encryption between you and your recipient to protect sensitive data.</p>
<p style="text-align: justify;">So, tor will help protect your incoming and outgiong data (routed through tor) from someone watching your outgoing infromation, like your ISP or a man in the middle. Data is encrypted at the application layer multiple times, so it&#8217;s pretty damn safe through the tor network until it hits the exit node. Keep in mind, you don&#8217;t know who the exit node is or who is watching it, and data is back in its original form at the exit node. If the data itself contains information that could link back to you, like name, address, location, email, accounts, and other personal identifiers, someone could read through the data and know it&#8217;s yours and what you&#8217;re sending/receiving. From a purely technical standpoint, though, there isn&#8217;t a very feasible way to trace the data to its origin in the transport or internet layers.</p>
<p style="text-align: justify;">First, install tor:</p>
<pre>$sudo pacman -S tor</pre>
<p style="text-align: justify;">Now  enable Tor DNS forwarder , this will allow tor to resolve your DNS hostnames through the tor network, helping to keep your browsing habits secret. (This resolves only A records):</p>
<pre>#nano /etc/tor/torrc
 | DNSPort 9053
 | AutomapHostsOnResolve 1
 | AutomapHostsSuffixes .exit,.onion</pre>
<p style="text-align: justify;">restart tor:</p>
<pre>#/etc/rc.d/tor restart</pre>
<p style="text-align: justify;">Now that tor is configured and running, we can configure applications to pump their data through it. In our browser, for instance, we can go to the network settings and run traffic through tor&#8217;s locally-running socks 5 proxy server:</p>
<pre>127.0.0.1:9050</pre>
<p style="text-align: justify;">Some applications do not have options exposed to manually set a proxy to go through, so we can use tor-resolve and torrify on those. tor-resolve will resolve DNS records for domains (currently only A records), as DNS resolving itself happens independent of applications and can be telling of the sites we are visiting. torrify acts as a sort of wrapper around an application so that its network activity runs through tor. Here is an example using BitchX:</p>
<pre>#tor-resolve &lt;irc.server.domain&gt;
#torify BitchX</pre>
<p style="text-align: justify;">Tor provides a pre-packaged Tor Browser which runs inside of a tor sandbox and comes bundled with Vidalia, a GUI tool for managing tor. Currently, a modified firefox setup is used, with NoScript and other plugins installed to prevent JavaSript, cookies, and so forth from leaking identifying information. Furthermore, it can be set (and is by default) to force sites to use https for end-to-end application-layer</p>
<pre>$tar -xf tor-broswer.tar.bz
$cd ./tor-browser
$sudo ./start-tor-browser</pre>
<p style="text-align: justify;">NOW YOU CAN START READING ONLINE SAFELY <img src='http://www.speakingcode.com/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> </p>
<p style="text-align: justify;">Using tor, we get a nice layer of obfuscation that makes it <em>very</em> difficult (though theoretically possible) for anyone in the network to monitor our data and see what we are doing by sniffing network packets, and at the same time anonymizes us on the outside so that potentially malicious or invasive intruders on the other end cannot gather personalized information on us, such as our IP addressand hostname, which could be used to identify or locate us, among other things.</p>
<p style="text-align: justify;">Here&#8217;s a few things to remember about tor:</p>
<ul>
<li><strong>tor&#8217;s efficacy largely depends on the number of nodes in the network</strong>. More nodes mean more random paths between nodes are possible, increasing the complexity of tracing the origin and reducing the feasability of theoretically possible attacks based on having a holistic view of the tor network. Also, because all traffic is encrypted in multiple layers and sent through multiple nodes, using tor can be slow at times. That said, <strong>be nice and give back by allowing tor to run even at times you aren&#8217;t using it</strong>, acting as a node for other people&#8217;s encrypted traffic to pass through. Additionally, <strong>don&#8217;t use tor for heavy data transfer &#8211; bit torrent and the like is typically frowned upon</strong>.</li>
<li><strong>Exit nodes, and the people running running exit nodes (which is set by choice, not default) , are exposed to the outside internet</strong>. While historically not very problematic, it does put them in a position of risk as any data exiting from a given node can be linked to the person running it by his/her ISP. While it may not hold against them in court, it can put them in violation of the law, or their isp&#8217;s terms of use, if other torizens abuse the network. <strong>Don&#8217;t use tor to do anything illegal, unethical, or which might cause problems for an exit node operator</strong>. Use it to protect your right to privacy as a law-abiding citizen and your right protection from snoopers, scam artists, advertisers, and the like.</li>
<li><strong>Tor is only one layer of obfuscation</strong><strong>- data goes back to the public net in the same form that it came into tor</strong>. If you send out data which includes information that is not encrypted at the application layer, someone outside of the tor network can read it. <strong>Use end-to-end encryption</strong> in addition to tor, such as gpg, to protect transmissions between yourself and a known recipient, or use https to get end-to-end encryption over http.</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://www.speakingcode.com/2012/04/13/using-tor-to-anonymize-your-traffic/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Intel Announces 75 New Ultrabooks &#8211; Big Boost for Windows 8?</title>
		<link>http://www.speakingcode.com/2012/04/12/intel-announces-75-new-ultrabooks-big-boost-for-windows-8/</link>
		<comments>http://www.speakingcode.com/2012/04/12/intel-announces-75-new-ultrabooks-big-boost-for-windows-8/#comments</comments>
		<pubDate>Thu, 12 Apr 2012 18:33:24 +0000</pubDate>
		<dc:creator>rootlicker</dc:creator>
				<category><![CDATA[Rants]]></category>
		<category><![CDATA[android]]></category>
		<category><![CDATA[apple]]></category>
		<category><![CDATA[intel]]></category>
		<category><![CDATA[iphone]]></category>
		<category><![CDATA[microsoft]]></category>
		<category><![CDATA[notebook]]></category>
		<category><![CDATA[tablet]]></category>
		<category><![CDATA[touchscreen]]></category>
		<category><![CDATA[utlrabook]]></category>
		<category><![CDATA[windows 8]]></category>

		<guid isPermaLink="false">http://www.speakingcode.com/?p=290</guid>
		<description><![CDATA[Fusion tablet/notebooks with multi-touch support are coming, and it looks like Windows 8 will be the host. Intel announced yesterday [...]]]></description>
			<content:encoded><![CDATA[<div class="mceTemp" style="text-align: justify;">
<dl id="attachment_293" class="wp-caption alignright" style="width: 310px;">
<dt class="wp-caption-dt"><a href="http://www.speakingcode.com/wp-content/uploads/2012/04/lenovo_ideapad_yoga_speakingcode.com-windows-8-metro-ultrabook-75-models-intel-notebook.jpg"><img class="size-medium wp-image-293" title="lenovo_ideapad_yoga_speakingcode.com-windows-8-metro-ultrabook-75-models-intel-notebook" src="http://www.speakingcode.com/wp-content/uploads/2012/04/lenovo_ideapad_yoga_speakingcode.com-windows-8-metro-ultrabook-75-models-intel-notebook-300x200.jpg" alt="lenovo_ideapad_yoga_speakingcode.com-windows-8-metro-ultrabook-75-models-intel-notebook" width="300" height="200" /></a></dt>
<dd class="wp-caption-dd">Fusion tablet/notebooks with multi-touch support are coming, and it looks like Windows 8 will be the host.</dd>
</dl>
</div>
<p style="text-align: justify;">Intel announced yesterday that <a title="75 New Ultrabook Models" href="http://h4ck.tk/c" target="_blank">75 Ultrabook models are under development</a>. “Ultrabook” is Intel’s trademark description of notebook-type devices that specifies certain requirements for weight, thickness, battery life, time-to-wake, etc. Manufacturers have to meet the spec guidelines in order to label a product as an Utlrabook.</p>
<p style="text-align: justify;">Of the new models, most or all of them will have touchscreens and several models will be tablet hybrids. <a title="Screensize breakdown on next line of Ultrabooks - speakingcode.com" href="http://h4ck.tk/e" target="_blank">Several screen sizes are included in this lineup</a>, ranging from under 13 inches to over 15.  Intel also expects that some models will reach starting prices as low as $699.</p>
<p style="text-align: justify;">Windows 8 looks to be the choice operating system to roll out with this next generation of Ultrabooks. This is a big deal for Microsoft as it will instantaneously bring strong market penetration into the tablet/touchscreen sector, assuming consumers purchase these new models. With new features like multi-touch screens, and with the low-weight, fast-boot, slim-design requirements enforced by Intel, it&#8217;s probably safe to bet that reception will be good.</p>
<p style="text-align: justify;">This is good news not only for Microsoft and Intel, but also for developers who are jumping in with Windows 8 Metro development. We all know Microsoft doesn&#8217;t hurt for market share on traditional desktops and notebooks, but the mobile and tablet world is a different ecosystem, with more players and rapid changes. With Windows Phone receiving less-than-sizzling response from the masses, it was unclear if and how Microsoft would come in as a formidable competitor in the mobile world, and how Windows 8 would fair as a sort of &#8220;fusion&#8221; tablet/desktop OS. Will desktop and notebook users care about light-weight, &#8220;consumption&#8221; based, touch-enabled apps in an envrionment typically reserved for feature-rich, complex productivity suits?</p>
<p style="text-align: justify;">Manufacturers are swooping in on the Ultrabook concept, blurring the lines between notebooks and tablets and pushing the categories of mobile computing.  This will likely get Windows 8 into the hands of many consumers who are interested in using devices in a mobile and/or touch-centric modality and thus will embrace the Metro platform, making it worth the time and costs for Metro app developers. At the very least, there will be no shortage of devices for their creations to run on.</p>
<p style="text-align: justify;">How will this change the spectrum in consideration of Apple and Android? This will be the really interesting thing to watch. Android seems to be less than dominant in the tablet market, but it looks like Microsoft is coming full force. Will the &#8220;seamless experience&#8221; Win 8 provides across desktop, notebook, and tablet pull users away from Apple and Android tablet devices? My guess is that Microsoft plans to extend the Win 8 &#8220;unification&#8221; to the phone not far down the road, which may drive a lot of consumers to a Windows phone in the future.</p>
<p style="text-align: justify;">Speaking of Windows 8 Metro development, I have started to dabble in that area just a tad. Expect more posts with some code details soon!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.speakingcode.com/2012/04/12/intel-announces-75-new-ultrabooks-big-boost-for-windows-8/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Why I&#8217;m Loving Scala</title>
		<link>http://www.speakingcode.com/2012/02/29/why-im-loving-scala/</link>
		<comments>http://www.speakingcode.com/2012/02/29/why-im-loving-scala/#comments</comments>
		<pubDate>Thu, 01 Mar 2012 01:38:38 +0000</pubDate>
		<dc:creator>rootlicker</dc:creator>
				<category><![CDATA[Java]]></category>
		<category><![CDATA[Scala]]></category>

		<guid isPermaLink="false">http://www.speakingcode.com/?p=267</guid>
		<description><![CDATA[I very recently (like, four days ago) got turned on to Scala. I&#8217;d &#8220;heard of it&#8221; a few times with [...]]]></description>
			<content:encoded><![CDATA[<p>I very recently (like, four days ago) got turned on to <a title="The Scala Programming Langauge" href="http://www.scala-lang.org/" target="_blank">Scala</a>. I&#8217;d &#8220;heard of it&#8221; a few times with phrases like, &#8220;It&#8217;s like Java mixed with Haskell&#8221;. I always like to learn about new languages, see what they offer, and understand what makes them unique in both syntax and in approach. So when a good developer friend of mine told me to check it out last week, I did,</p>
<p>Ok, so if you don&#8217;t know, Scala is a programming language. It&#8217;s not exactly new, but it has been gaining momentum and attention for the past couple of years. Being a full time developer in a Java shop, the first thing I did was Google search &#8220;Scala vs Java&#8221;, which led me to<a title="Scala &gt; Java" href="http://www.youtube.com/watch?v=PKc5IwHG68k" target="_blank"> this great presentation by Dan Rosen of Marakana, at a San Francisco JUG meeting</a> (btw, you can <a title="Scala &gt; Java slides" href="http://marakana.com/static/courseware/scala/presentation/scala%20%3E%20java.html" target="_blank">view the slides here</a>). The sweet sugary syntax and powerful expressive capabilities he demonstrated were enticing to say the least. Some notes about Scala:</p>
<ul>
<li>Compiles to Java byte-code which runs on the JVM</li>
<li>Fully compatible with Java. Scala can use and extend Java classes, reference Java libraries, etc.</li>
<li>100% object-oriented. Everything is an object in Scala, including methods, control structures, expressions&#8230; everything.</li>
<li>Fully supportive of functional programming paradigm (avoiding state and mutable data)</li>
<li>Clean syntax, powerful control structures (like for/yield, case) that typically &#8220;surpass&#8221; Java, and powerful compiler inferences</li>
</ul>
<p>So, enough words. This is not a guide to Scala, go to http://scala-lang.org if that&#8217;s what you&#8217;re looking for.  Let&#8217;s look at some code already. I&#8217;m going to borrow an example for quicksort. In Java, quicksort might look like this:</p>
<pre class="brush:java">public void quickSort(int[] a, int l, int r)
{
  int i = l;
  int j = r;
  int pivot a[(l+r)/2]

  if (array.length &lt;= 1)
    return;

  while(i &lt;= j)
  {
    while(a[i] &lt; pivot)
      i++;
    while(a[j] &gt; pivot)
      j--;
    if(i &lt; j)
    {
      swap(a, i++, j--);
    }
  }
  if (l &lt; j) sort(a, l, j);
  if (j &lt; r) sort(a, i, r);
}
public void swap(int[] a, int i, int j)
{
  int t = a[i];
  a[i] = a[j];
  a[j] = t;
}</pre>
<p>That&#8217;s the kind of code that makes you feel all smart and cool when you know what it does, and makes you frustrated as hell if you don&#8217;t. If you know quicksort, you can probably look at the code and recognize this is it, but the code itself doesn&#8217;t really express the algorithm. It is tough to follow and step through and understand at a high level. Even being fluent in Java syntax, I still have to press my brain a little to follow exactly whats going on</p>
<p>Now, in Scala, we could do this in two ways. Although a cleaner syntax than Java IMO, the imperative-style shows just a tad bit of syntactical difference, so I&#8217;m going to skip that and show a functional style.  This comes from Martin Odesrky&#8217;s free pdf book Scala By Example (available on the scala-lang.org site).</p>
<pre class="brush:scala">def sort(a: Array[Int]): Array[Int] =
{
  if (a.length &lt;=1) a
  else
  {
    val pivot = a(a.length / 2)
    Array.concat(
      sort(a filter (pivot &gt;)),
           a filter (pivot ==),
      sort(a filter (pivot &lt;)))
  }
}</pre>
<p>Holy hell, I did it from memory! The people who worked hard writing and understanding Java implementations of quicksort just got their feelings hurt! Coming from an imperative background, the syntax will look a bit strange, but a few things should stand out clearly.</p>
<p>First of all, this is a recursive function. We are defining a method called sort, which makes calls to itself.  We see a base case,  and we see that we are concatenating the results of the recursive calls. Without knowing any Scala syntax, and despite this example being chock-full of shorthand, it&#8217;s not a stretch to decipher that we are breaking our problem into three smaller ones and joining them back together. If you know quicksort, it&#8217;s plainly obvious: set a pivot value; break the array down into sub-arrays, one with elements less than the pivot, one with elements equal to the pivot, and one with elements greater than the pivot; sort them and join them back together. We only sort the first and last, as the middle sub-array&#8217;s elements are all equal to pivot and thus to each other (a = c, b = c -&gt; a = c).</p>
<p>In Scala, methods that take one argument don&#8217;t have to be written as <em>object.method(arg)</em>, we can simply write <em>object method arg</em>. This is demonstrated by the + operator:<em> x + 5</em> is the same as <em>x.+(5)</em> (it turns out that in Scala, we can name methods using special characters like +, -, *, etc.). So <em>a filter (pivot &gt;)</em> is equivalent to <em>a.filter(pivot &gt;)</em></p>
<p>The filter method of the Array class is one such method, which takes a function as its one argument. This isn&#8217;t like java, where we wrap a method with return type A as an argument for another method whose parameter is also type A, and the first method&#8217;s <em>evaluation</em> becomes the argument, such as in <em>System.out.println(something.toString())</em>. Rather, the function <em>itself</em> is an object that is being passed through. The filter method has a signature that places constraint on the function it accepts as an argument: it must take a value of type T as input and return a Boolean. Array.filter&#8217;s signature looks something like this:</p>
<pre class="brush:scala">def filter(p: T =&gt; Boolean): Array[T]</pre>
<p>which defines the function argument, as p, and states that p maps a T object to a Boolean value. In our case, our array is type Int, so we pass a Boolean function that takes an Int as input. We use a shorthand, (pivot &gt;), which is equivalent to <em>(x =&gt; pivot &gt; x)</em>, which says &#8220;give me an input x, and I will tell you if x is greater than the value stored in pivot&#8221;.</p>
<p>In Java we might see something like this:</p>
<pre class="brush:java">sort(
  a.filter(new FilterTest&lt;Int&gt;()
  {
    @override
    public boolean test(Int i)
    {
      if i &gt; pivot
        return true;
      else
        return false;
    }
  })
);</pre>
<p>i.e. we call sort, and as its argument (an ArrayList) we call the a.filter() method (which returns an ArrayList), passing as its argument an anonymous class implementation of the FilterTest interface, which implements the boolean test() method. In accordance, the class for ArrayList would have something like:</p>
<pre class="brush:java">public Interface FilterTest&lt;T&gt;
{
  public boolean test(T item);
}

public ArrayList&lt;T&gt; filter(FilterTest ft)
{
  ArrayList&lt;T&gt; outputArray = new ArrayList&lt;T&gt;();
  for (T item : this)
  {
    if ft.test(item)
      outputArray.add(item);
  }
}</pre>
<p>In Scala we get all of that long filter call, with the anonymous class implmentation of the FilterTest , instead just by saying <em>a filter (value &gt;)</em>, awesome. This is just a taste of the power of Scala, which doesn&#8217;t stop there. I can&#8217;t wait to dive in and learn even more of it.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.speakingcode.com/2012/02/29/why-im-loving-scala/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Creating a Streaming Audio App for Android with MediaPlayer, AudioManager and Service classes</title>
		<link>http://www.speakingcode.com/2012/02/22/creating-a-streaming-audio-app-for-android-with-android-media-mediaplayer-android-media-audiomanager-and-android-app-service/</link>
		<comments>http://www.speakingcode.com/2012/02/22/creating-a-streaming-audio-app-for-android-with-android-media-mediaplayer-android-media-audiomanager-and-android-app-service/#comments</comments>
		<pubDate>Wed, 22 Feb 2012 23:03:34 +0000</pubDate>
		<dc:creator>rootlicker</dc:creator>
				<category><![CDATA[Android]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[android]]></category>
		<category><![CDATA[android service]]></category>
		<category><![CDATA[audio]]></category>
		<category><![CDATA[media]]></category>
		<category><![CDATA[mediaplayer]]></category>
		<category><![CDATA[service]]></category>
		<category><![CDATA[streaming audio]]></category>

		<guid isPermaLink="false">http://www.speakingcode.com/?p=249</guid>
		<description><![CDATA[First, a little disclaimer. The MediaPlayer class is a fairly complex class with many states that directly affect how it [...]]]></description>
			<content:encoded><![CDATA[<p style="text-align: justify;">First, a little disclaimer. The MediaPlayer class is a fairly complex class with many states that directly affect how it functions and what methods can be called on it without getting exceptions and breakage. As such, don&#8217;t take this as an end-all solution; it is a rough start on how to use it effectively. There are other approaches, many documented online, and probably some that are more robust than this one. Anyway, rtfm if you intend to use any of the mentioned classes below. The Android Developer dev guides and reference pages are a good start, and I would suggest you at least glance at them before continuing &#8211; time is short and I don&#8217;t have enough of it to write out detailed explanations right now.</p>
<ul style="text-align: justify;">
<li><a href="http://developer.android.com/guide/topics/media/mediaplayer.html">http://developer.android.com/guide/topics/media/mediaplayer.html</a></li>
<li><a href="http://developer.android.com/reference/android/media/MediaPlayer.html">http://developer.android.com/reference/android/media/MediaPlayer.html</a></li>
<li><a href="http://developer.android.com/reference/android/media/AudioManager.html">http://developer.android.com/reference/android/media/AudioManager.html</a></li>
</ul>
<p style="text-align: justify;">The same goes for the <em>android.app.Service </em>class &#8211; Android services are on the more complex side of Android app development, and the Service class lends itself to several models of use. Read up on it&#8230;</p>
<ul style="text-align: justify;">
<li><a href="http://developer.android.com/guide/topics/fundamentals/services.html">http://developer.android.com/guide/topics/fundamentals/services.html</a></li>
<li><a href="http://developer.android.com/guide/topics/fundamentals/bound-services.html">http://developer.android.com/guide/topics/fundamentals/bound-services.html</a></li>
<li><a href="http://developer.android.com/reference/android/app/Service.html">http://developer.android.com/reference/android/app/Service.html</a></li>
<li><a href="http://developer.android.com/reference/android/content/ServiceConnection.html">http://developer.android.com/reference/android/content/ServiceConnection.html</a></li>
<li><a href="http://developer.android.com/reference/android/os/IBinder.html">http://developer.android.com/reference/android/os/IBinder.html</a></li>
</ul>
<p style="text-align: justify;">So here is the basic approach we will follow. First, we will extend the <em>android.media.MediaPlayer</em> class into a new class that provides a bit of state management (using an enum of states), because the MediaPlayer class involves a lot of state but doesn&#8217;t provide any methods to directly get the state (oops!).</p>
<p style="text-align: justify;">Then we will write a Service class that extends <em>android.app.Service</em> to run outside of any Activity, so that music playback can continue when the user leaves (not &#8220;exits&#8221;) the app. The service will implement some interfaces to get notices from the MeidaPlayer, like when it&#8217;s prepared and when it has an error, etc. Additionally, the service will implement an internal, public class that extends <em>android.os.Binder </em>(an implementation of the <em>android.os.IBinder</em> interface), which is used by the Activity/Activities that want to bind to the service to interact with it. An instance of this class is returned by the <em>public IBinder Service.onBind()</em> method which our service will override from its parent Service class. In our case, this internal class will have one method, called <em>getService()</em>, which returns an object reference to the instance of the Service itself. Then the bound Activity can simply make direct method calls on the instance of the service, via the object reference returned by getService().</p>
<p style="text-align: justify;">The &#8220;main&#8221; Activity that uses the Service will have a private implementation of the <em>android.content.ServiceConnection</em> interface (I think technically this implementation is an anonymous class, but damn those Java terms), which will be passed TO the service (via <em>bindService()</em>) when the Activity binds to it. This will have the <em>onServiceConnected()</em> method where the getService() method mentioned above will be called, and the Activity will pass an object reference to itself BACK to the service, so that the service can call callback methods on the Activity &#8211; this will allow the Activity to update controls and displays based on what&#8217;s happening with the service and media player &#8211; like setting the play/pause button to the right state.</p>
<p style="text-align: justify;">Of course, the Activity will have methods to control playback, as well as show some status to the user. In addition, it will have some helper methods to check, when it starts, whether the service is already running or not, so it will know if it should bind to the existing instance or create a new one. This will allow the user to leave and return to the app freely without interfering with playback.</p>
<p style="text-align: justify;">In addition to those classes, we will have a few more supporting classes. The <em>StreamStation</em> class will represent a station for streaming audio, holding the name and url as members, and having some compare methods we will use in our Activity to determine the currently playing station when we bind to the Service. The <em>StreamStationSpinnerAdapter</em> class will be used to populate the Spinner object we use to select different streams. And lastly, the <em>CONSTANTS </em>class will hold some constants like an array of StreamStation objects&#8230;</p>
<p style="text-align: justify;">As mentioned in the disclaimer, this is not a complete solution, but rather a start. There are other things to consider like phone interruptions, sharing the playback device with other apps, and more, which are not addressed in this example. Just a start..</p>
<pre class="brush:java">package com.speakingcode.android.media.mediaplayer;

import java.io.IOException;

import android.media.AudioManager;
import android.util.Log;

import com.speakingcode.audio.media.streamStation.StreamStation;

/**
 * A subclass of android.media.MediaPlayer which provides methods for
 * state-management, data-source management, etc.
 * @author rootlicker http://speakingcode.com
 */
public class StatefulMediaPlayer extends android.media.MediaPlayer {
	/**
	 * Set of states for StatefulMediaPlayer:&lt;br&gt;
	 * EMPTY, CREATED, PREPARED, STARTED, PAUSED, STOPPED, ERROR
	 * @author rootlicker
	 */
	public enum MPStates {
		EMPTY, CREATED, PREPARED, STARTED, PAUSED, STOPPED, ERROR
	}

	private MPStates mState;
	private StreamStation mStreamStation;

	public StreamStation getStreamStation() {
		return mStreamStation;
	}

	/**
	 * Sets a StatefulMediaPlayer's data source as the provided StreamStation
	 * @param streamStation the StreamStation to set as the data source
	 */
	public void setStreamStation(StreamStation streamStation) {
		this.mStreamStation = streamStation;
		try {
			setDataSource(streamStation.getStationUrl());
			setState(MPStates.CREATED);
		}
		catch (Exception e) {
			Log.e("StatefulMediaPlayer", "setDataSource failed");
			setState(MPStates.ERROR);
		}
	}

	/**
	 * Instantiates a StatefulMediaPlayer object.
	 */
	public StatefulMediaPlayer() {
		super();
		setState(MPStates.CREATED);
	}

	/**
	 * Instantiates a StatefulMediaPlayer object with the Audio Stream Type
	 * set to STREAM_MUSIC and the provided StreamStation's URL as the data source.
	 * @param streamStation The StreamStation to use as the data source
	 */
	public StatefulMediaPlayer(StreamStation streamStation) {
		super();
		this.setAudioStreamType(AudioManager.STREAM_MUSIC);
		this.mStreamStation = streamStation;
		try {
			setDataSource(mStreamStation.getStationUrl());
			setState(MPStates.CREATED);
		}
		catch (Exception e) {
			Log.e("StatefulMediaPlayer", "setDataSourceFailed");
			setState(MPStates.ERROR);
		}
	}

	@Override
	public void reset() {
		super.reset();
		this.mState = MPStates.EMPTY;
	}

	@Override
	public void start() {
		super.start();
		setState(MPStates.STARTED);
	}

	@Override
	public void pause() {

		super.pause();
		setState(MPStates.PAUSED);

	}

	@Override
	public void stop() {
		super.stop();
		setState(MPStates.STOPPED);
	}

	@Override
	public void release() {
		super.release();
		setState(MPStates.EMPTY);
	}

	@Override
	public void prepare() throws IOException, IllegalStateException {
		super.prepare();
		setState(MPStates.PREPARED);
	}

	@Override
	public void prepareAsync() throws IllegalStateException {
		super.prepareAsync();
		setState(MPStates.PREPARED);
	}

	public MPStates getState() {
		return mState;
	}

	/**
	 * @param state the state to set
	 */
	public void setState(MPStates state) {
		this.mState = state;
	}

	public boolean isCreated() {
		return (mState == MPStates.CREATED);
	}

	public boolean isEmpty() {
		return (mState == MPStates.EMPTY);
	}

	public boolean isStopped() {
		return (mState == MPStates.STOPPED);
	}

	public boolean isStarted() {
		return (mState == MPStates.STARTED || this.isPlaying());
	}

	public boolean isPaused() {
		return (mState == MPStates.PAUSED);
	}

	public boolean isPrepared() {
		return (mState == MPStates.PREPARED);
	}
}</pre>
<pre class="brush:java">/**
 *
 */
package com.speakingcode.android.media.mediaplayer;

import android.app.Notification;
import android.app.PendingIntent;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.media.AudioManager;
import android.media.MediaPlayer;
import android.media.MediaPlayer.OnBufferingUpdateListener;
import android.media.MediaPlayer.OnErrorListener;
import android.media.MediaPlayer.OnInfoListener;
import android.media.MediaPlayer.OnPreparedListener;
import android.os.Binder;
import android.os.IBinder;
import android.util.Log;

import com.speakingcode.android.media.mediaplayer.StatefulMediaPlayer.MPStates;
import com.speakingcode.audio.media.streamStation.StreamStation;

import com.speakingcode.example.android.MainActivity;

/**
 * An extension of android.app.Service class which provides access to a StatefulMediaPlayer.&lt;br&gt;
 * @author rootlicker http://speakingcode.com
 * @see com.speakingcode.android.media.mediaplayer.StatefulMediaPlayer
 */
public class MediaPlayerService extends Service implements OnBufferingUpdateListener, OnInfoListener, OnPreparedListener, OnErrorListener {
	private StatefulMediaPlayer mMediaPlayer			= new StatefulMediaPlayer();
	private final Binder mBinder						= new MediaPlayerBinder();
	private IMediaPlayerServiceClient mClient;

	/**
	 * A class for clients binding to this service. The client will be passed an object of this class
	 * via its onServiceConnected(ComponentName, IBinder) callback.
	 */
	public class MediaPlayerBinder extends Binder {
		/**
		 * Returns the instance of this service for a client to make method calls on it.
		 * @return the instance of this service.
		 */
		public MediaPlayerService getService() {
			return MediaPlayerService.this;
		}

	}

	/**
	 * Returns the contained StatefulMediaPlayer
	 * @return
	 */
	public StatefulMediaPlayer getMediaPlayer() {
		return mMediaPlayer;
	}

	/**
	 * Initializes a StatefulMediaPlayer for streaming playback of the provided StreamStation
	 * @param station The StreamStation representing the station to play
	 */
	public void initializePlayer(StreamStation station) {
		mClient.onInitializePlayerStart("Connecting...");
		mMediaPlayer = new StatefulMediaPlayer(station);

		mMediaPlayer.setOnBufferingUpdateListener(this);
		mMediaPlayer.setOnInfoListener(this);
		mMediaPlayer.setOnPreparedListener(this);
		mMediaPlayer.prepareAsync();
	}

	/**
	 * Initializes a StatefulMediaPlayer for streaming playback of the provided stream url
	 * @param streamUrl The URL of the stream to play.
	 */
	public void initializePlayer(String streamUrl) {

		mMediaPlayer = new StatefulMediaPlayer();
		mMediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
		try {
			mMediaPlayer.setDataSource(streamUrl);
		}
		catch (Exception e) {
			Log.e("MediaPlayerService", "error setting data source");
			mMediaPlayer.setState(MPStates.ERROR);
		}
		mMediaPlayer.setOnBufferingUpdateListener(this);
		mMediaPlayer.setOnInfoListener(this);
		mMediaPlayer.setOnPreparedListener(this);
		mMediaPlayer.prepareAsync();
	}

	@Override
	public IBinder onBind(Intent arg0) {
		return mBinder;
	}

	@Override
	public void onBufferingUpdate(MediaPlayer player, int percent) {

	}

	@Override
	public boolean onError(MediaPlayer player, int what, int extra) {
		mMediaPlayer.reset();
		mClient.onError();
		return true;
	}

	@Override
	public boolean onInfo(MediaPlayer mp, int what, int extra) {
		return false;
	}

	@Override
	public void onPrepared(MediaPlayer player) {
		mClient.onInitializePlayerSuccess();
		startMediaPlayer();

	}

	@Override
	  public int onStartCommand(Intent intent, int flags, int startId) {
	      return START_STICKY;
	  }

	/**
	 * Pauses the contained StatefulMediaPlayer
	 */
	public void pauseMediaPlayer() {
		Log.d("MediaPlayerService","pauseMediaPlayer() called");
		mMediaPlayer.pause();
		stopForeground(true);

	}

	/**
	 * Sets the client using this service.
	 * @param client The client of this service, which implements the IMediaPlayerServiceClient interface
	 */
	public void setClient(IMediaPlayerServiceClient client) {
		this.mClient = client;
	}

	 /**
	 * Starts the contained StatefulMediaPlayer and foregrounds the service to support
	 * persisted background playback.
	 */
	public void startMediaPlayer() {
		Context context = getApplicationContext();

		//set to foreground
		Notification notification = new Notification(android.R.drawable.ic_media_play, "MediaPlayerService",
		        System.currentTimeMillis());
		Intent notificationIntent = new Intent(this, MainActivity.class);
		notificationIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
		PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, notificationIntent, 0);

		CharSequence contentTitle = "MediaPlayerService Is Playing";
		CharSequence contentText = mMediaPlayer.getStreamStation().getStationLabel();
		notification.setLatestEventInfo(context, contentTitle,
		        contentText, pendingIntent);
		startForeground(1, notification);

		Log.d("MediaPlayerService","startMediaPlayer() called");
		mMediaPlayer.start();
	}

	/**
	 * Stops the contained StatefulMediaPlayer.
	 */
	public void stopMediaPlayer() {
		stopForeground(true);
		mMediaPlayer.stop();
		mMediaPlayer.release();
	}

	public void resetMediaPlaer() {
		stopForeground(true);
		mMediaPlayer.reset();
	}

}</pre>
<pre class="brush:java">package com.speakingcode.android.media.mediaplayer;

/**
 * @author rootlicker http://speakingcode.com
 */
public interface IMediaPlayerServiceClient {

	/**
	 * A callback made by a MediaPlayerService onto its clients to indicate that a player is initializing.
	 * @param message A message to propagate to the client
	 */
	public void onInitializePlayerStart(String message);

	/**
	 * A callback made by a MediaPlayerService onto its clients to indicate that a player was successfully initialized.
	 */
	public void onInitializePlayerSuccess();

	/**
	 *  A callback made by a MediaPlayerService onto its clients to indicate that a player encountered an error.
	 */
	public void onError();
}</pre>
<pre class="brush:java">package com.speakingcode.example.android;

import android.app.Activity;
import android.app.ActivityManager;
import android.app.ActivityManager.RunningServiceInfo;
import android.app.ProgressDialog;
import android.content.ComponentName;
import android.content.Context;
import android.content.DialogInterface;
import android.content.DialogInterface.OnCancelListener;
import android.content.Intent;
import android.content.ServiceConnection;
import android.net.Uri;
import android.os.Bundle;
import android.os.IBinder;
import android.util.Log;
import android.view.Gravity;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemSelectedListener;
import android.widget.Spinner;
import android.widget.ToggleButton;

import com.speakingcode.example.android;
import com.speakingcode.android.media.mediaplayer.IMediaPlayerServiceClient;
import com.speakingcode.android.media.mediaplayer.MediaPlayerService;
import com.speakingcode.android.media.mediaplayer.StatefulMediaPlayer;
import com.speakingcode.android.media.mediaplayer.MediaPlayerService.MediaPlayerBinder;
import com.speakingcode.audio.media.streamStation.StreamStationSpinnerAdapter;
import com.speakingcode.audio.media.streamStation.StreamStation;

/**
 * @author rootlicker http://speakingcode.com
 */
public class MainActivity extends Activity
		implements IMediaPlayerServiceClient {
	private StatefulMediaPlayer mMediaPlayer;
	private StreamStation mSelectedStream = CONSTANTS.DEFAULT_STREAM_STATION;
	private MediaPlayerService mService;
	private boolean mBound;

	private ProgressDialog mProgressDialog;

	/** Called when the activity is first created. */
	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.main);
		bindToService();
		mProgressDialog = new ProgressDialog(this);

		initializeButtons();
		setupStationPicker();
    }

	@Override
	public boolean onCreateOptionsMenu(Menu menu)
	{
		MenuInflater inflater = getMenuInflater();
		inflater.inflate(R.menu.main_activity_menu, menu);
		return true;
	}

	@Override
	public boolean onOptionsItemSelected(MenuItem item)
	{
		// Handle item selection
		switch (item.getItemId())
		{
			case R.id.menuClose:
				shutdownActivity();
				return true;
			default:
				return super.onOptionsItemSelected(item);
		}
	}

	/**
	 * Binds to the instance of MediaPlayerService. If no instance of MediaPlayerService exists, it first starts
	 * a new instance of the service.
	 */
	public void bindToService() {
        Intent intent = new Intent(this, MediaPlayerService.class);

        if (MediaPlayerServiceRunning()) {
			// Bind to LocalService
	        bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
		}
		else {
			startService(intent);
	        bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
		}

	}

	/**
	 * Sets up the stationPicker spinner
	 */
	public void setupStationPicker() {
		Spinner stationPicker = (Spinner) findViewById(R.id.stationPicker);
	    StreamStationSpinnerAdapter adapter = new StreamStationSpinnerAdapter(
	            this, android.R.layout.simple_spinner_item);

	    //populate adapter with stations
	    for(StreamStation st : CONSTANTS.STATIONS)
	    {
	    	adapter.add(st);
	    }
	    adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
	    stationPicker.setAdapter(adapter);
	    stationPicker.setOnItemSelectedListener(new OnItemSelectedListener()
	    {

		    @Override
			public void onItemSelected(AdapterView&lt;?&gt; parent, View view, int pos, long id) {
		    	StreamStation selectedStreamStation = (StreamStation) parent.getItemAtPosition(pos);

		    	if (selectedStreamStation != mSelectedStream)
		    	{
		    		mService.stopMediaPlayer();
		    		mSelectedStream = selectedStreamStation;
		    		mService.initializePlayer(mSelectedStream);
		    	}
		    }

		    @Override
			public void onNothingSelected(AdapterView&lt;?&gt; parent)
		    {
		      // Do nothing.
		    }

	    });
	}

	/**
	 * Initializes buttons by setting even handlers and listeners, etc.
	 */
	private void initializeButtons() {
		// PLAY/PAUSE BUTTON
		final ToggleButton playPauseButton = (ToggleButton) findViewById(R.id.playPauseButton);
		playPauseButton.setOnClickListener(new OnClickListener() {

			@Override
			public void onClick(View v) {
				if (mBound) {
					mMediaPlayer = mService.getMediaPlayer();

					//pressed pause -&gt;pause
					if (!playPauseButton.isChecked()) {

						if (mMediaPlayer.isStarted()) {
							mService.pauseMediaPlayer();
						}

					}

					//pressed play
					else if (playPauseButton.isChecked()) {
						// STOPPED, CREATED, EMPTY, -&gt; initialize
						if (mMediaPlayer.isStopped()
								|| mMediaPlayer.isCreated()
								|| mMediaPlayer.isEmpty())
						{
							mService.initializePlayer(mSelectedStream);
						}

						//prepared, paused -&gt; resume play
						else if (mMediaPlayer.isPrepared()
								|| mMediaPlayer.isPaused())
						{
							mService.startMediaPlayer();
						}

					}
				}
			}

		});
	}

	/**
	 * Defines callbacks for service binding, passed to bindService()
	 */
	private ServiceConnection mConnection = new ServiceConnection() {
    	@Override
        public void onServiceConnected(ComponentName className, IBinder serviceBinder) {
    		Log.d("MainActivity","service connected");

            //bound with Service. get Service instance
            MediaPlayerBinder binder = (MediaPlayerBinder) serviceBinder;
            mService = binder.getService();

            //send this instance to the service, so it can make callbacks on this instance as a client
            mService.setClient(MainActivity.this);
            mBound = true;

            //Set play/pause button to reflect state of the service's contained player
            final ToggleButton playPauseButton = (ToggleButton) findViewById(R.id.playPauseButton);
    		playPauseButton.setChecked(mService.getMediaPlayer().isPlaying());

    		//Set station Picker to show currently set stream station
    		Spinner stationPicker = (Spinner) findViewById(R.id.stationPicker);
    		if(mService.getMediaPlayer() != null &amp;&amp; mService.getMediaPlayer().getStreamStation() != null) {
	    		for (int i = 0; i &lt; CONSTANTS.STATIONS.length; i++) {
	    			if (mService.getMediaPlayer().getStreamStation().equals(CONSTANTS.STATIONS[i])) {
	    				stationPicker.setSelection(i);
	    				mSelectedStream = (StreamStation) stationPicker.getItemAtPosition(i);
	    			}

	    		}
    		}

        }

        @Override
        public void onServiceDisconnected(ComponentName arg0) {
            mBound = false;
        }
    };

    /** Determines if the MediaPlayerService is already running.
     * @return true if the service is running, false otherwise.
     */
    private boolean MediaPlayerServiceRunning() {

    	ActivityManager manager = (ActivityManager) getSystemService(ACTIVITY_SERVICE);

    	for (RunningServiceInfo service : manager.getRunningServices(Integer.MAX_VALUE)) {
            if ("com.speakingcode.example.android.MediaPlayerService".equals(service.service.getClassName())) {
                return true;
            }
        }

        return false;
    }

    public void onInitializePlayerSuccess() {
		mProgressDialog.dismiss();

		final ToggleButton playPauseButton = (ToggleButton) findViewById(R.id.playPauseButton);
		playPauseButton.setChecked(true);
	}

    public void onInitializePlayerStart(String message) {
		mProgressDialog = ProgressDialog.show(this, "", message, true);
		mProgressDialog.getWindow().setGravity(Gravity.TOP);
		mProgressDialog.setCancelable(true);
		mProgressDialog.setOnCancelListener(new OnCancelListener() {

			@Override
			public void onCancel(DialogInterface dialogInterface) {
					MainActivity.this.mService.resetMediaPlaer();
					final ToggleButton playPauseButton = (ToggleButton) findViewById(R.id.playPauseButton);
					playPauseButton.setChecked(false);
			}

		});

	}

	@Override
	public void onError() {
			mProgressDialog.cancel();
	}

    /**
     * Closes unbinds from service, stops the service, and calls finish()
     */
    public void shutdownActivity() {

    	if (mBound) {
			mService.stopMediaPlayer();
			// Detach existing connection.
			unbindService(mConnection);
			mBound = false;
    	 }

        Intent intent = new Intent(this, MediaPlayerService.class);
    	stopService(intent);
    	finish();

    }

}</pre>
<pre class="brush:java">/**
 *
 */
package com.speakingcode.audio.media.streamStation;

/**
 * A class to represent Streaming media stations. Holds label, URL, and other information.
 * @author rootlicker http://speakingcode.com
 */
public class StreamStation {
	private String mStationLabel;
	private String mStationUrl;

	/**
	 * Constructs a new StreamStation object with empty label and URL
	 */
	public StreamStation() {
		this("","");
	}
	/**
	 * Constructs a new StreamStation object with specified label and URL
	 * @param stationLabel
	 * @param stationUrl
	 */
	public StreamStation(String stationLabel, String stationUrl) {
		mStationLabel = stationLabel;
		mStationUrl = stationUrl;
	}

	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		StreamStation other = (StreamStation) obj;
		if (mStationLabel == null) {
			if (other.mStationLabel != null)
				return false;
		}
		else if (!mStationLabel.equals(other.mStationLabel))
			return false;
		if (mStationUrl == null) {
			if (other.mStationUrl != null)
				return false;
		}
		else if (!mStationUrl.equals(other.mStationUrl))
			return false;
		return true;
	}

	/**
	 * Gets the station's label as a String
	 * @return the station label
	 */
	public String getStationLabel() {
		return mStationLabel;
	}

	/**
	 * Gets the station's URL, as a String
	 * @return the URL of the station
	 */
	public String getStationUrl() {
		return mStationUrl;
	}

	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result
				+ ((mStationLabel == null) ? 0 : mStationLabel.hashCode());
		result = prime * result
				+ ((mStationUrl == null) ? 0 : mStationUrl.hashCode());
		return result;
	}

	/**
	 * Sets a String as the station's label
	 * @param stationLabel the label to set
	 */
	public void setStationLabel(String stationLabel) {
		this.mStationLabel = stationLabel;
	}

	/**
	 * Set's a String as the station's URL
	 * @param stationUrl the URL of the Station
	 */
	public void setStationUrl(String mStationUrl) {
		this.mStationUrl = mStationUrl;
	}

}</pre>
<pre class="brush:java">package com.speakingcode.audio.media.streamStation;

import android.content.Context;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.TextView;

/**
 * @author rootlicker http://speakingcode.com
 *
 */
public class StreamStationSpinnerAdapter extends ArrayAdapter&lt;StreamStation&gt; {
	int mTextViewResourceId;
	Context mContext;

	public StreamStationSpinnerAdapter(Context context, int textViewResourceId) {
		super(context, textViewResourceId);
		this.mTextViewResourceId = textViewResourceId;
		mContext = context;
	}

	@Override
	public View getView(int position, View convertView, ViewGroup parent) {
		TextView tv = (TextView)(super.getView(position, convertView, parent));
		tv.setText(getItem(position).getStationLabel());
		return tv;
	}

	@Override
	public View getDropDownView(int position, View convertView, ViewGroup parent) {
		TextView tv = (TextView)(super.getDropDownView(position, convertView, parent));
		tv.setText(getItem(position).getStationLabel());
		return tv;
	}
}</pre>
<pre class="brush:java">package com.speakingcode.example.android;

import com.speakingcode.audio.media.streamStation.StreamStation;

/**
 * @author rootlicker http://speakingcode.com
 *
 */
public class CONSTANTS {
	public static final String DUBSTEP_HQ_URL    = "http://lemon.citrus3.com:8062";
	public static final String DUBSTEP_LQ_URL    = "http://lemon.citrus3.com:8048";
	public static final String DNB_HQ_URL        = "http://lemon.citrus3.com:8144";
	public static final String GRIME_HQ_URL      = "http://lemon.citrus3.com:8120";

	public static final String DUBSTEP_HQ_LABEL  = "FILTH.FM Dubstep Hi-Fi (192kb/s)";
	public static final String DUBSTEP_LQ_LABEL  = "FILTH.FM Dubstep Lo-Fi (96kb/s)";
	public static final String DNB_HQ_LABEL      = "FILTH.FM D&amp;B Hi-Fi (192kb/s)";
	public static final String GRIME_HQ_LABEL    = "FILTH.FM Grime Hi-Fi (192kb/s)";
	public static final StreamStation[] STATIONS =
		{
			new StreamStation(DUBSTEP_HQ_LABEL, DUBSTEP_HQ_URL),
			new StreamStation(DUBSTEP_LQ_LABEL, DUBSTEP_LQ_URL),
			new StreamStation(DNB_HQ_LABEL, DNB_HQ_URL),
			new StreamStation(GRIME_HQ_LABEL, GRIME_HQ_URL)
		};
	public static final StreamStation DEFAULT_STREAM_STATION = STATIONS[0];
}</pre>
]]></content:encoded>
			<wfw:commentRss>http://www.speakingcode.com/2012/02/22/creating-a-streaming-audio-app-for-android-with-android-media-mediaplayer-android-media-audiomanager-and-android-app-service/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Dynamic Directory Listing with JavaScript Image Swaps using PHP</title>
		<link>http://www.speakingcode.com/2012/02/04/dynamic-directory-listing-with-javascript-image-swaps-using-php/</link>
		<comments>http://www.speakingcode.com/2012/02/04/dynamic-directory-listing-with-javascript-image-swaps-using-php/#comments</comments>
		<pubDate>Sat, 04 Feb 2012 23:10:03 +0000</pubDate>
		<dc:creator>rootlicker</dc:creator>
				<category><![CDATA[HTML]]></category>
		<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[images]]></category>
		<category><![CDATA[rollovers]]></category>
		<category><![CDATA[web development]]></category>

		<guid isPermaLink="false">http://www.speakingcode.com/?p=236</guid>
		<description><![CDATA[I&#8217;ve used this enough that I should jot it down somewhere&#8230; Let&#8217;s suppose we want to quickly list the contents [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve used this enough that I should jot it down somewhere&#8230; Let&#8217;s suppose we want to quickly list the contents of a directory using PHP. We&#8217;ll assume the php file is in the root index directory, and the files we want to list are in a sub-directory /files/</p>
<pre class="brush:php">&lt;?
$dirName = "./files/";
$dir = opendir($dirName);
while ($fileName = readdir($dir))
{
  echo("$filename&lt;br&gt;");
}
?&gt;</pre>
<p>This simple example, other than not being pretty, has one obvious drawback &#8211; it will list the . and .. shortcut references to the working directory its parent directory. We can wrap the echo statement in an if statement so that it is only called when $fileName does not point to . or ..</p>
<pre class="brush:php">&lt;?
$dirName = "./files/";
$dir = opendir($dirName);
while ($fileName = readdir($dir))
{
  if ( ($fileName != ".") &amp;&amp; ($fileName != "..") )
  {
    echo ("$filename");
  }
}
?&gt;</pre>
<p>Now lets have a little fun.  First, instead of listing the files as plain text, we will make them hyperlinks&#8230;</p>
<pre class="brush:php">&lt;?
$dirName = "./files/";
$dir = opendir($dirName);
while ($fileName = readdir($dir))
{
  if ( ($fileName != ".") &amp;&amp; ($fileName != "..") )
  {
    echo ("&lt;a href=\"$dirName/$filename\"&gt;$fileName&lt;a/&gt;&amp;ltbr&amp;gt");
  }
}
?&gt;</pre>
<p>Hyperlinks are nifty, but rollover image swaps are a lot more fun. Assuming we have two image files named img_icon_on.png and img_icon_off.png for the onMouseOver and onMouseOut events, we want our end-result links to look something like this:</p>
<pre class="brush:xml">&lt;a
	href="somefile"
	onMouseOver = "document.img_icon.src='layout_images/nav_images/img_icon_on.png'"
	onMouseOut  = "document.img_icon.src='layout_images/nav_images/img_icon_off.png'"&gt;
&lt;img
	src="layout_images/nav_images/img_icon_off.png"
	name="img_icon"
	border="0"
/&gt;&lt;/a&gt;</pre>
<p>The caveat here is that we need each img tag to have a unique value assigned to the name attribute, and we need our document.&lt;resourcename&gt;.src portions of the onMouseOver and onMouseOut event handlers to reflect the unique img name they correspond to. We can simply append the name attribute and the DOM element names with the name of the file the link will reference. Using str_replace() we can remove any . characters from the filename so that it won&#8217;t break the output HTML:</p>
<pre class="brush:php">&lt;?
$dirName = "./files/";
$dir = opendir($dirName);
while ($fileName = readdir($dir))
{
	if (($fileName != ".") &amp;&amp; ($fileName != ".."))
	{
		$cleanFileName = str_replace(".","",$fileName);
		echo ("
			&lt;a
				href=\"$dirName/$fileName\"
				onMouseOver = \"document.img_icon_$cleanFileName.src='layout_images/nav_images/img_icon_on.png'\"
				onMouseOut  = \"document.img_icon_$cleanFileName.src='layout_images/nav_images/img_icon_off.png'\"
			\"&gt;
			&lt;img
				src=\"layout_images/nav_images/img_icon_off.png\"
				name=\"img_icon_$cleanFileName\"
				border=\"0\"
			/&gt;&lt;/a&gt;
		");
	}
}
closedir($dir);
?&gt;</pre>
]]></content:encoded>
			<wfw:commentRss>http://www.speakingcode.com/2012/02/04/dynamic-directory-listing-with-javascript-image-swaps-using-php/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>New Android App &#8211; FILTH FM Radio!</title>
		<link>http://www.speakingcode.com/2012/02/04/new-android-app-filth-fm-radio/</link>
		<comments>http://www.speakingcode.com/2012/02/04/new-android-app-filth-fm-radio/#comments</comments>
		<pubDate>Sat, 04 Feb 2012 22:45:41 +0000</pubDate>
		<dc:creator>rootlicker</dc:creator>
				<category><![CDATA[Android]]></category>
		<category><![CDATA[Rants]]></category>
		<category><![CDATA[android]]></category>
		<category><![CDATA[mediaplayer]]></category>
		<category><![CDATA[music]]></category>
		<category><![CDATA[streaming audio]]></category>

		<guid isPermaLink="false">http://www.speakingcode.com/?p=231</guid>
		<description><![CDATA[Check out the new Filth.FM Android app! I&#8217;ve launched a new app under a company I co-operate, Skematic Design. It [...]]]></description>
			<content:encoded><![CDATA[<div class="mceTemp" style="text-align: justify;">
<dl id="attachment_232" class="wp-caption alignleft" style="width: 139px;">
<dt class="wp-caption-dt"><a href="http://www.speakingcode.com/wp-content/uploads/2012/02/filthfm_screenshot_speakingcode.com-speaking-code-programming-java-javascript-android-security-infosec-hacking.jpg"><img class="size-full wp-image-232 " title="filthfm_screenshot_speakingcode.com-speaking-code-programming-java-javascript-android-security-infosec-hacking" src="http://www.speakingcode.com/wp-content/uploads/2012/02/filthfm_screenshot_speakingcode.com-speaking-code-programming-java-javascript-android-security-infosec-hacking.jpg" alt="filthfm_screenshot_speakingcode.com-speaking-code-programming-java-javascript-android-security-infosec-hacking" width="129" height="230" /></a></dt>
<dd class="wp-caption-dd">Check out the new Filth.FM Android app!</dd>
</dl>
</div>
<p style="text-align: justify;">I&#8217;ve launched a new app under a company I co-operate, <a title="Skematic Design - Web, Multimedia, App Development, SEO, and More" href="http://skematicdesign.com" target="_blank">Skematic Design</a>. It provides the ability to stream media from the internet radio station <a title="FILTH FM - dubstep, drum and base, grime and more, 24/7" href="http://filth.fm" target="_blank">filth.fm</a> They play electronic music, particularly dubstep, drum and base, and grime, so if you&#8217;re into that you&#8217;ll be in heaven.</p>
<p style="text-align: justify;">To implement the app, I had to use the Android MediaPlayer class, actually extending it into a new class in order to manage the player&#8217;s state more easily. I also implemented a Service sub-class to provide background playback, etc. I will be adding some articles about how to do that soon. Meanwhile, check out the app at <a title="FiLTH.FM For Android" href="https://market.android.com/details?id=fm.filth.android" target="_blank">https://market.android.com/details?id=fm.filth.android</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.speakingcode.com/2012/02/04/new-android-app-filth-fm-radio/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

