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

<channel>
	<title>ThePizzy.net/blog &#187; Projects</title>
	<atom:link href="http://thepizzy.net/blog/category/projects/feed/" rel="self" type="application/rss+xml" />
	<link>http://thepizzy.net/blog</link>
	<description>Solving the complex in 140 characters or less...</description>
	<lastBuildDate>Mon, 02 Jan 2012 15:55:48 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.4-alpha-19719</generator>
<xhtml:meta xmlns:xhtml="http://www.w3.org/1999/xhtml" name="robots" content="noindex" />
		<item>
		<title>The Pizzy: A look forward to 2012 &#8211; Slim-Down Tech</title>
		<link>http://thepizzy.net/blog/2012/01/the-pizzy-a-look-forward-to-2012-slim-down-tech/</link>
		<comments>http://thepizzy.net/blog/2012/01/the-pizzy-a-look-forward-to-2012-slim-down-tech/#comments</comments>
		<pubDate>Mon, 02 Jan 2012 15:54:19 +0000</pubDate>
		<dc:creator>[[Neo]]</dc:creator>
				<category><![CDATA[How To]]></category>
		<category><![CDATA[Projects]]></category>
		<category><![CDATA[Technology]]></category>
		<category><![CDATA[forecast]]></category>
		<category><![CDATA[slim-down tech]]></category>
		<category><![CDATA[update]]></category>
		<category><![CDATA[weight-loss]]></category>

		<guid isPermaLink="false">http://thepizzy.net/blog/?p=1353</guid>
		<description><![CDATA[Last year I helped protect yourself online; this year, I help protect yourself in real life. I'll start a series of posts about various weight-loss technologies I will be using to lose ~5 lbs a month without any medication, just sheer effort.]]></description>
			<content:encoded><![CDATA[<p><img class="size-medium wp-image-1354 alignleft" title="Weight Loss Scale" src="http://thepizzy.net/blog/wp-content/uploads/2012/01/weight-loss1-300x277.jpg" alt="Image Source: pyxismprooffice.com" width="300" height="277" /></p>
<p>Last year, I did a series on how to <a title="How to find yourself online" href="http://thepizzy.net/blog/2011/01/how-to-find-yourself-online/">protect yourself </a>and <a title="How to plug your personal information leaks" href="http://thepizzy.net/blog/2011/01/how-to-plug-your-personal-information-leaks/">your privacy online</a>, with the biggest issue being <a title="Configuring your Facebook Profile Privacy Settings" href="http://thepizzy.net/blog/2011/01/configuring-your-facebook-profile-privacy-settings/">sites like Facebook</a>. The instructions helped a lot of people, but were soon out-dated since Facebook released updated security controls and privacy settings to make the process even easier. I still had several people <a title="How to Handle Online Harassment &amp; Cyber Stalking" href="http://thepizzy.net/blog/2011/01/how-to-handle-online-harassment-cyber-stalking/" target="_blank">seeking advice for handling cyber stalkers</a>, which is still an ongoing issue with the internet, and one that <a href="http://www.cnn.com/2011/12/16/tech/web/stalking-on-twitter-protected/index.html" target="_blank">the courts have decided falls under &#8220;Free Speech&#8221;</a> (however, a &#8220;public figure&#8221; of sorts filed this case after he had a falling out with a friend).</p>
<p>However, last year, I also used various pieces of technology to lose nearly 30 lbs over 6 months, without taking any medication. All it takes is an awareness of what you&#8217;re doing, what you&#8217;re eating, and an understanding of what your body is telling you.</p>
<p>My goal last year was to lose 100 lbs in 12 months, in preparation for my wedding. However, the closer it got to the wedding, the less time I had to keep it up, and I relapsed. This year, I take it from the top again, and document what types of technology I&#8217;m using, what things I&#8217;m doing, and how you can do it too. Everything I&#8217;ll be doing will have to fit into a 40 hr work week, with family events and 7-8 hours of sleep each night &#8211; so this will be a completely realistic routine for anyone to follow &#8211; if they make it a priority, like watching sitcoms, playing video games, and going out. The realistic target weight-loss is about 5 lbs a month. Too slow and it seems pointless, too fast and it will all come back.</p>
<p>If you&#8217;re starting a weight-loss goal this year, then I&#8217;ll leave you with the #1 tip for doing it: KEEP MOVING. If you&#8217;re moving, you&#8217;re burning calories, whether it&#8217;s walking, running, climbing steps, whatever&#8230;just keep moving.</p>
<p>Be looking for posts this year with tips, ideas, technologies, and my progress updates. I&#8217;ll also be interested in hearing any other tips that people want to share.</p>

<!-- start wp-tags-to-technorati 1.02 -->

<p class='technorati-tags'>Technorati Tags: <a class='technorati-link' href='http://technorati.com/tag/forecast' rel='tag' target='_blank'>forecast</a>, <a class='technorati-link' href='http://technorati.com/tag/slim-down+tech' rel='tag' target='_blank'>slim-down tech</a>, <a class='technorati-link' href='http://technorati.com/tag/update' rel='tag' target='_blank'>update</a>, <a class='technorati-link' href='http://technorati.com/tag/weight-loss' rel='tag' target='_blank'>weight-loss</a></p>

<!-- end wp-tags-to-technorati -->
]]></content:encoded>
			<wfw:commentRss>http://thepizzy.net/blog/2012/01/the-pizzy-a-look-forward-to-2012-slim-down-tech/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Jasper: Just a store platform experience, reworked</title>
		<link>http://thepizzy.net/blog/2011/02/jasper-just-a-store-platform-experience-reworked/</link>
		<comments>http://thepizzy.net/blog/2011/02/jasper-just-a-store-platform-experience-reworked/#comments</comments>
		<pubDate>Mon, 14 Feb 2011 01:08:03 +0000</pubDate>
		<dc:creator>[[Neo]]</dc:creator>
				<category><![CDATA[Jasper]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[Projects]]></category>
		<category><![CDATA[Technology]]></category>
		<category><![CDATA[ajax]]></category>
		<category><![CDATA[catalog.xml]]></category>
		<category><![CDATA[Coding]]></category>
		<category><![CDATA[jasper]]></category>
		<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[kodingen.com]]></category>
		<category><![CDATA[MySQL]]></category>
		<category><![CDATA[objinfo.xml]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[yahoo store platform]]></category>
		<category><![CDATA[yahoo! stores]]></category>

		<guid isPermaLink="false">http://thepizzy.net/blog/?p=1132</guid>
		<description><![CDATA[Jasper is an experiment in creating a Yahoo! Store Editor and CMS using only the cloud-based coding solution from Kodingen.com]]></description>
			<content:encoded><![CDATA[<p><img class="alignleft size-medium wp-image-1133" title="Jasper Logo" src="http://thepizzy.net/blog/wp-content/uploads/2011/02/logo-name-300x171.png" alt="Jasper Logo" width="300" height="171" />For the past 3 years, I&#8217;ve been working on a store that uses the Yahoo! Store platform. At first, the user interface for the web page design and page object models was easy to grasp (both the prefab versions and the custom ones I had access to), but going through the entire rewrite process was a pain &#8211; the biggest of which was the requirement of perfection. If a mistake was made in any field names or data-types it held, the whole object model had to be scrapped and started over. They&#8217;ve made minor improvements over the past 3 years to their Merchant Solutions side of things, but they have been extremely minor. One thing that hasn&#8217;t changed is the interface to edit pages.</p>
<p>There are two methods of doing the editing, depending on the Yahoo! Store platform that you have. If you&#8217;re on the Legacy version, you must go to the page itself, and click edit. This provides you with a series of fields and input boxes for each type of field. No intelligence in the design of what those fields are for or differentiation in how they interact.</p>
<p>If you&#8217;re on the Merchant Solutions platform, then you have the option of going directly to the page still, or you can do it in a flat-file pseudo database-like UI which is nothing more than a search-by-field interface, which presents you with a different-looking (but still the same) interface for editing the page.</p>
<p>Over the next few months, I&#8217;m going to embark on a web-based interface for importing the legacy store feed (objinfo.xml, which can&#8217;t be customized) and see what can be done with the data as far as modifying it, preparing it, cleaning it, and exporting it back to the store. I&#8217;m also going to attempt to code it entirely using <a href="http://kodingen.com" target="_blank">Kodingen.com</a>. I&#8217;ve done a highly customized version of this concept for the company I currently work for (at the time of this post), but none of the code will be reused from that project, and this project will have different, and limited features (in some areas, and expanded in other areas), but for a different data model. In some areas, this application will be more limited (since it&#8217;s working with a standardized data format, rather than a customized &#8220;catalog.xml&#8221; feed from Merchant Solutions. Once this basic version is solid, I may start working on a customized version, or even offering a customizing service to handle the catalog.xml file.</p>
<p>Some things I&#8217;d like to do differently with this basic version is:</p>
<ul>
<li>create an install process (a la phpBB)</li>
<li>extensive automation, and possibly some AI concepts</li>
<li>learn more about object-oriented design and how it can be extended conceptually</li>
<li>experiment with some various php and javascript frameworks</li>
</ul>
<p>There are plenty of other feature sets that I&#8217;ve learned and developed in addition to these in the past and plan to use as well. So we&#8217;ll see how this goes, and I&#8217;ll post some updates here. Depending on what I plan to do with it, I may or may not open-source it. If I do, I&#8217;ll host it on Google Code.</p>

<!-- start wp-tags-to-technorati 1.02 -->

<p class='technorati-tags'>Technorati Tags: <a class='technorati-link' href='http://technorati.com/tag/ajax' rel='tag' target='_blank'>ajax</a>, <a class='technorati-link' href='http://technorati.com/tag/catalog.xml' rel='tag' target='_blank'>catalog.xml</a>, <a class='technorati-link' href='http://technorati.com/tag/Coding' rel='tag' target='_blank'>Coding</a>, <a class='technorati-link' href='http://technorati.com/tag/jasper' rel='tag' target='_blank'>jasper</a>, <a class='technorati-link' href='http://technorati.com/tag/JavaScript' rel='tag' target='_blank'>JavaScript</a>, <a class='technorati-link' href='http://technorati.com/tag/kodingen.com' rel='tag' target='_blank'>kodingen.com</a>, <a class='technorati-link' href='http://technorati.com/tag/MySQL' rel='tag' target='_blank'>MySQL</a>, <a class='technorati-link' href='http://technorati.com/tag/objinfo.xml' rel='tag' target='_blank'>objinfo.xml</a>, <a class='technorati-link' href='http://technorati.com/tag/PHP' rel='tag' target='_blank'>PHP</a>, <a class='technorati-link' href='http://technorati.com/tag/Programming' rel='tag' target='_blank'>Programming</a>, <a class='technorati-link' href='http://technorati.com/tag/yahoo+store+platform' rel='tag' target='_blank'>yahoo store platform</a>, <a class='technorati-link' href='http://technorati.com/tag/yahoo%21+stores' rel='tag' target='_blank'>yahoo! stores</a></p>

<!-- end wp-tags-to-technorati -->
]]></content:encoded>
			<wfw:commentRss>http://thepizzy.net/blog/2011/02/jasper-just-a-store-platform-experience-reworked/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>How to Connect to SQL through Windows Authenticated ODBC in PHP</title>
		<link>http://thepizzy.net/blog/2011/02/how-to-connect-to-sql-through-windows-authenticated-odbc-in-php/</link>
		<comments>http://thepizzy.net/blog/2011/02/how-to-connect-to-sql-through-windows-authenticated-odbc-in-php/#comments</comments>
		<pubDate>Sun, 06 Feb 2011 20:41:09 +0000</pubDate>
		<dc:creator>[[Neo]]</dc:creator>
				<category><![CDATA[How To]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[Projects]]></category>
		<category><![CDATA[Technology]]></category>
		<category><![CDATA[how to connect to sql server in php with odbc]]></category>
		<category><![CDATA[microsoft odbc]]></category>
		<category><![CDATA[microsoft sql server]]></category>
		<category><![CDATA[mssql]]></category>
		<category><![CDATA[odbc]]></category>
		<category><![CDATA[odbc connection]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[php odbc connection]]></category>
		<category><![CDATA[sql]]></category>
		<category><![CDATA[sql server odbc connection]]></category>
		<category><![CDATA[windows authenticated odbc]]></category>
		<category><![CDATA[windows authenticated odbc connection]]></category>
		<category><![CDATA[windows odbc connection]]></category>

		<guid isPermaLink="false">http://thepizzy.net/blog/?p=1116</guid>
		<description><![CDATA[If you use MSSQL over ODBC, connecting w/ PHP is simply a DOMAIN\WEBSERVER acct on the MSSQL server &#038; the DSN in PHP's odbc_connect()]]></description>
			<content:encoded><![CDATA[<p><img class="alignleft size-full wp-image-1125" title="ODBC Connection" src="http://thepizzy.net/blog/wp-content/uploads/2011/02/8787717937219497341.png" alt="" width="256" height="256" />For about the last year, I&#8217;ve been creating a CMS (content management system), for the automatic management and maintenance of my company&#8217;s eCommerce site, on the Yahoo! Store platform. The software imports the entire store automatically, runs a series of cleanup processes with about a dozen different criteria, saves the changes it has made, exports the modified pages, and makes them available to download from Jada&#8217;s interface. This automation cuts the need for about 3-4 people doing a weeks&#8217; worth of work, and does it all automatically in 10-30 minutes. The one thing it doesn&#8217;t do, is the one cleanup process that takes the longest, and requires the most human thought: comparing every product&#8217;s available options on the site, and checking them against actual inventory in the order management software.</p>
<p>Until now.</p>
<p>Our current order management software runs as a MS Access front-end to a MSSQL 2005 server backend through and ODBC DSN connection. This connection has been limited to MS Access and MS Excel application/queries, and thus, was the limiting factor to writing this most-complex cleanup process into Jada. The most difficult part in my development was finding an understandable article describing how to make an ODBC call, and then actually get the data back, in the same simple manner that one makes a MySQL query. The real issue has been <strong>once the connection is closed, the result cannot be accessed</strong>. I had to find that out the hardway, via <a href="http://msdn.microsoft.com/en-us/library/ms811006.aspx" target="_blank">Microsoft&#8217;s convoluted documentation on using ODBC</a>.</p>
<p>Here&#8217;s the code I&#8217;ve used to make the ODBC connection in PHP (unfortunately my blog&#8217;s template can&#8217;t handle actual code right now):</p>
<p><a href="http://thepizzy.net/blog/wp-content/uploads/2011/02/2011-02-06_13131.png"><img class="aligncenter size-full wp-image-1119" title="function odbcQuery()" src="http://thepizzy.net/blog/wp-content/uploads/2011/02/2011-02-06_13131.png" alt="" width="630" height="786" /></a></p>
<h1>Code Breakdown</h1>
<p>We&#8217;ll start creating a function that makes an ODBC connection, passes it an SQL query, then parses the data into a table/array and return the array.</p>
<h2>Function call</h2>
<pre>function odbcQuery($sql, $attempt="") {</pre>
<p>When we call the function, we&#8217;ll provide the SQL Query we want executed, and an optional description of what we&#8217;re trying to do with the query. In this way, if it errors, an semantic error will be displayed along with the technical one to help locate the code easily.</p>
<h2>Database Connection</h2>
<pre>// Establish an odbc connection with the database
$link = odbc_connect("My_DSN_Name", "", "");</pre>
<p>When running <strong><a href="http://us3.php.net/manual/en/function.odbc-connect.php" target="_blank">odbc_connect()</a></strong> it takes 3 parameters:</p>
<ul>
<li>the DSN; Server,Port; or Server/SQLInstance</li>
<li>username</li>
<li>password</li>
</ul>
<p>When connecting using Windows Authentication &amp; a DSN (as this example is about), there are some caveats and things to remember:</p>
<ol>
<li>On the web server, the User running the Web Service process needs to be a User with permission to access the SQL Server.
<ol>
<li>In my case, the user running the web server is <strong>SYSTEM</strong>, and so the user trying to access the SQL server is &#8220;<strong>DOMAIN\COMPUTERNAME$</strong>&#8220;.</li>
<li>There is no password for a SYSTEM account, and so on the SQL Server needs to have a user created named &#8220;<strong>DOMAIN\COMPUTERNAME$</strong>&#8220;.</li>
<li>Due to some security concerns, I&#8217;ve decided to give the account read-only access to the database I want to access. You&#8217;ll need to consult your own IT Administrator or security advisor for your security concerns.</li>
</ol>
</li>
<li>In the odbc_connect() statement, you then only need the name of the DSN (which I assume has already been configured on the Web Server you&#8217;re using) , followed by two null-quotes: &#8220;&#8221;.</li>
</ol>
<p>This creates an active link via ODBC to the SQL Server&#8230;supposedly</p>
<h2>Database Connection Checking &amp; Error Handling</h2>
<pre>if (!$link) {
	die('Could not connect: '.odbc_error().': '.odbc_errormsg());
} else {</pre>
<p>Next, we check the link . If it just flat-out doesn&#8217;t exist, then we kill the program, throw an error message that will read: &#8220;Could not connect: &lt;insert odbc error code&gt;:  &lt;insert odbc error text&gt;&#8221;. Otherwise, we move on&#8230;</p>
<h2>Sending the SQL Query &amp; Checking Response</h2>
<pre>$data = odbc_exec($link, $sql);
if($data === false) {
	echo "ODBC Query: ".$sql."&lt;br /&gt;&lt;br /&gt;";
	die("ODBC Query failed:  ".$attempt."&lt;br /&gt;Error: ".odbc_error());
} else {</pre>
<p>Now that we have a valid link to the database, we&#8217;ll send a request for <strong>data</strong> using the <strong><a href="http://us3.php.net/manual/en/function.odbc-exec.php" target="_blank">odbc_exec()</a></strong> function. This function sends the connection resource (<strong>$link</strong>) and the SQL Query we want run (<strong>$sql</strong>). It will return a &#8220;ODBC result identifier&#8221; or <em><strong>false</strong></em>.</p>
<p>Since a result identifier could, I assume, be the number 0 (zero) I want to ensure that <strong>$data</strong> is actually <strong><em>false</em></strong> and not just zero. That&#8217;s where the triple === comes in. When doing conditional statements, using == will convert the data being compared into a true/false value, where <em>zero or nothing</em> = <strong><em>false</em></strong> and <em>anything else</em> = <strong><em>true</em></strong>. When you use === you test for an actual boolean value, meaning <em>anything including zero</em> = <strong><em>true</em></strong> and <strong><em>false = false</em></strong>.</p>
<p>If the query failed, and resulted in a <strong><em>false</em></strong> result, we&#8217;ll display an error message: &#8220;ODBC Query: &lt;insert actual SQL Query&gt; // ODBC Query failed: &lt;insert query description&gt; // Error: &lt;insert ODBC error code&gt;&#8221;. Otherwise, we&#8217;ll move on&#8230;</p>
<h2>Parsing the Query Results &#8211; Column Headers</h2>
<pre>// Initialization
$row = $fields = $records = $result = array(); 	

// Get the result's column names
$count = odbc_num_fields($data);
for($x=1;$x&lt;=$count;$x++) {
	$fields[] = odbc_field_name($data, $x);
}</pre>
<p>We start off by initializing all the variables we&#8217;re going to use in the next bit of code, to make sure they&#8217;re empty.</p>
<p>Then we&#8217;ll run <strong><a href="http://us3.php.net/manual/en/function.odbc-num-fields.php" target="_blank">odbc_num_fields()</a></strong> over the <strong>$data</strong> to get the number of columns we need to iterate through. For columns, the counting starts at 1, so the for-loop starts at 1.</p>
<p>Iterate through each column name and add it to an array, called <strong>$fields</strong>:</p>
<pre>Array (
	[0] =&gt; field_name_1
	[1] =&gt; field_name_2
	[2] =&gt; field_name_3
)</pre>
<h2>Parsing the Query Results &#8211; Records</h2>
<pre>
<pre>// Get the result's data: array[record#][column#] = value
$count = odbc_num_rows($data);
for($x=0;$x&lt;$count;$x++) {
	odbc_fetch_into($data, $row, $x);
	array_push($records,$row);
}</pre>
</pre>
<p>Then we run <strong><a href="http://us3.php.net/manual/en/function.odbc-num-rows.php" target="_blank">odbc_num_rows()</a></strong> over the $data to get the number of rows we need to iterate through. For rows, the counting starts at 0, so the for-loop starts at 0.</p>
<p>Iterate through each record row and insert it to a temporary array <strong>$row</strong> using <strong><a href="http://us3.php.net/manual/en/function.odbc-fetch-into.php" target="_blank">odbc_fetch_into()</a></strong>. Then take <strong>$row</strong> and put it into an array of records, <strong>$records</strong> giving you something like this:</p>
<pre>Array (
	[0] =&gt; Array (
		[0] =&gt; record_1_column_1
		[1] =&gt; record_1_column_2
		[2] =&gt; record_1_column_3
	)
	[1] =&gt; Array (
		[0] =&gt; record_2_column_1
 		[1] =&gt; record_2_column_2
 		[2] =&gt; record_2_column_3
  	)
	[2] =&gt; Array (
 		[0] =&gt; record_3_column_1
 		[1] =&gt; record_3_column_2
 		[2] =&gt; record_3_column_3
  	)
 )</pre>
<h2>Making the data useable</h2>
<p>Now that we&#8217;ve got two tables/arrays of data &#8211; the field/column names, and each record&#8217;s array of data &#8211; it&#8217;s time to make it usable in a format that we can consistently expect to be returned. There are two ways to do this. We can create an array listind every record as an array with column_name keys and values</p>
<pre>// Return data in the format: array[record_id][column_name] = value
foreach($records as $rid =&gt; $record) {
	foreach($fields as $key =&gt; $name) {
		$result[$rid][$name] = $record[$key];
	}
}</pre>
<p>or we can list every column as an array of record id&#8217;s as keys and values.</p>
<pre>// Return the data in the format: array[column_name][record_id] = value
foreach($fields as $key =&gt; $name) {
	foreach($records as $record) {
		$result[$name][] = $record[$key];
	}
}</pre>
<p>Personally I find the first option to be more consistent with my results when calling a 2-dimensional result from MySQL queries, so it is the one I have gone with in my example at the start of the post, and in this description.</p>
<p>The <strong><a href="http://us3.php.net/manual/en/control-structures.foreach.php" target="_blank">foreach()</a></strong> statements describe a compilation of a <strong>$result</strong> array in this manner:</p>
<ol>
<li>For each item in the <strong>$records</strong> array, store the record_id as <strong>$rid</strong>, and the record array as <strong>$record</strong>.</li>
<li>Then for each item in the <strong>$fields</strong> array, store its cardinality as <strong>$key</strong> and it&#8217;s value/name as <strong>$name</strong>.</li>
<li>Then compile an array, iterating through each of the fields, storing this <strong>$record</strong>&#8216;s associated cardinality <strong>$key</strong>&#8216;s value into the <strong>$result</strong> array&#8217;s storage for this record&#8217;s id (<strong>$rid</strong>) under the appropriate field name.</li>
</ol>
<p>It&#8217;s a lot easier to grasp than it sounds. Basically, take array from the Query Results &#8211; Records section, and replace the # with the column name in each: [#] =&gt; record_y_column_x, but store it as a different array, called <strong>$results</strong>. The resulting array would look something like this:</p>
<pre>Array (
	[0] =&gt; Array (
		[column1] =&gt; record_1_column_1_data
		[column2] =&gt; record_1_column_2_data
		[column3] =&gt; record_1_column_3_data
	)
	[1] =&gt; Array (
		[column1] =&gt; record_2_column_1_data
 		[column2] =&gt; record_2_column_2_data
 		[column3] =&gt; record_2_column_3_data
  	)
	[2] =&gt; Array (
 		[column1] =&gt; record_3_column_1_data
 		[column2] =&gt; record_3_column_2_data
 		[column3] =&gt; record_3_column_3_data
  	)
 )</pre>
<h2>Close the connection, Return the result</h2>
<pre>		odbc_close($link);
		return $result;
	}
}</pre>
<p>Now that we&#8217;ve stored the data we need from the volatile <strong>$data</strong> variable returned from the SQL Query into <strong>$result</strong>, we can close the connection to <strong>$link</strong> using <strong><a href="http://us3.php.net/manual/en/function.odbc-close.php" target="_blank">odbc_close()</a></strong>, and then return <strong>$result</strong> for the program to do with it what it will.</p>
<h1>Conclusion</h1>
<p>This is just an example code that explains one way of many to extract a variable 1-2 dimension array of data from your SQL Query, using a Windows-Authenticated ODBC DSN connection. There are many other methods to do this, as well as security fixes, data scrubbing, and other modifications that one would probably want to do.</p>
<p>This is the first function I&#8217;ve written in any language to access an SQL Server via ODBC. This is also a function that has worked in tests, but that I have not yet put into production. I encourage you to take this bit of explanation and massage it into something that fits your needs in the code that you&#8217;re writing, and don&#8217;t rely on what I&#8217;ve got here as a written-in-stone example of good production-level code. This sample will change many times before I actually implement it.</p>
<p>Happy Hacking!</p>

<!-- start wp-tags-to-technorati 1.02 -->

<p class='technorati-tags'>Technorati Tags: <a class='technorati-link' href='http://technorati.com/tag/how+to+connect+to+sql+server+in+php+with+odbc' rel='tag' target='_blank'>how to connect to sql server in php with odbc</a>, <a class='technorati-link' href='http://technorati.com/tag/microsoft+odbc' rel='tag' target='_blank'>microsoft odbc</a>, <a class='technorati-link' href='http://technorati.com/tag/microsoft+sql+server' rel='tag' target='_blank'>microsoft sql server</a>, <a class='technorati-link' href='http://technorati.com/tag/mssql' rel='tag' target='_blank'>mssql</a>, <a class='technorati-link' href='http://technorati.com/tag/odbc' rel='tag' target='_blank'>odbc</a>, <a class='technorati-link' href='http://technorati.com/tag/odbc+connection' rel='tag' target='_blank'>odbc connection</a>, <a class='technorati-link' href='http://technorati.com/tag/PHP' rel='tag' target='_blank'>PHP</a>, <a class='technorati-link' href='http://technorati.com/tag/php+odbc+connection' rel='tag' target='_blank'>php odbc connection</a>, <a class='technorati-link' href='http://technorati.com/tag/sql' rel='tag' target='_blank'>sql</a>, <a class='technorati-link' href='http://technorati.com/tag/sql+server+odbc+connection' rel='tag' target='_blank'>sql server odbc connection</a>, <a class='technorati-link' href='http://technorati.com/tag/windows+authenticated+odbc' rel='tag' target='_blank'>windows authenticated odbc</a>, <a class='technorati-link' href='http://technorati.com/tag/windows+authenticated+odbc+connection' rel='tag' target='_blank'>windows authenticated odbc connection</a>, <a class='technorati-link' href='http://technorati.com/tag/windows+odbc+connection' rel='tag' target='_blank'>windows odbc connection</a></p>

<!-- end wp-tags-to-technorati -->
]]></content:encoded>
			<wfw:commentRss>http://thepizzy.net/blog/2011/02/how-to-connect-to-sql-through-windows-authenticated-odbc-in-php/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>WordPress Plugin: Bad Behavior</title>
		<link>http://thepizzy.net/blog/2011/01/wordpress-plugin-bad-behavior/</link>
		<comments>http://thepizzy.net/blog/2011/01/wordpress-plugin-bad-behavior/#comments</comments>
		<pubDate>Tue, 18 Jan 2011 16:00:25 +0000</pubDate>
		<dc:creator>[[Neo]]</dc:creator>
				<category><![CDATA[Reviews]]></category>
		<category><![CDATA[Technology]]></category>
		<category><![CDATA[Wordpress]]></category>
		<category><![CDATA[akismet]]></category>
		<category><![CDATA[bad behavior]]></category>
		<category><![CDATA[spam control]]></category>
		<category><![CDATA[spam protection]]></category>
		<category><![CDATA[wordpress plugins]]></category>

		<guid isPermaLink="false">http://thepizzy.net/blog/?p=1000</guid>
		<description><![CDATA[Since I started using a WordPress blog back in 2005, I&#8217;ve always had the Akismet WordPress plugin installed, and it was the sole provider of my spam protection. It has done an awesome job...]]></description>
			<content:encoded><![CDATA[<div id="attachment_1001" class="wp-caption alignleft" style="width: 235px"><img class="size-full wp-image-1001" title="Stop Spam" src="http://thepizzy.net/blog/wp-content/uploads/2011/01/stopspam1.jpg" alt="" width="225" height="192" /><p class="wp-caption-text">Source: dayoldcake.com</p></div>
<p>Since I started using a WordPress blog back in 2005, I&#8217;ve always had the <a href="http://wordpress.org/extend/plugins/akismet/" target="_blank">Akismet WordPress plugin</a> installed, and it was the sole provider of my spam protection. It has done an awesome job with an at-this-moment 99.843% accuracy rating, and has blocked 21,215 spam comments of which 6,686 of them were just in the last 6 months.</p>
<p>About a week ago, I found an <strong>additional</strong> spam blocking plugin that has also been very helpful. This one is called <a href="http://bad-behavior.ioerror.us/" target="_blank">Bad Behavior</a>.</p>
<p>In my observations over the last couple months, it appears that Akismet will block a comment that doesn&#8217;t seem to have any correlation to the content of the blog post. This would be why you see posts in your Spam queue that contain no links, no really harmful URLs, and just random text or pointless statements in the body of the comment. I&#8217;m sure Akismet is much more complicated than that, though, and I would assume there is a backend database of known spamming IPs/Hosts out there that it may also check against. However, the simplest, and likely initial method of detecting spam is via content.</p>
<p>Not with Bad Behavior. Instead of checking the content of the spam, it looks at the stuff you can&#8217;t see &#8211; the HTTP Headers, IP, User-Agent String, etc. From their own website&#8230;</p>
<blockquote><p>Bad Behavior analyzes the HTTP headers, IP address, and other metadata regarding the request to determine if it is spammy or malicious. This approach has proved, as one user said, “shockingly effective.” After all, spammers write their bots on the cheap, and have little incentive to code very well. If they could code very well, they probably wouldn’t be spammers.</p>
<p>When Bad Behavior looks at a request, it determines if the request matches a profile of known malicious or spammy activity, and falls outside the bounds of a normal human browsing the web. If so, the request is blocked. But a way out is provided for any human beings with unusual configurations or viruses/Trojans on their computer who may be blocked.</p>
<p style="text-align: right;">Source: <a href="http://bad-behavior.ioerror.us/documentation/how-it-works/" target="_blank">How Bad Behavior Works</a></p>
</blockquote>
<p>Here&#8217;s an example of some of the content it has blocked from this very blog&#8230;</p>
<p><a href="http://thepizzy.net/blog/wp-content/uploads/2011/01/2011-01-15_1512.png"><img class="aligncenter size-full wp-image-1003" title="Bad Behavior 1" src="http://thepizzy.net/blog/wp-content/uploads/2011/01/2011-01-15_1512.png" alt="" width="958" height="179" /></a></p>
<p>The image above is using a User-Agent string that includes the Windows version &#8220;Windows XP&#8221;. Anyone who has done their homework, and makes up a User-Agent string knows that Windows XP is actually Windows NT 5.x where X is the Service Pack number applied. Since Windows XP is not a valid User-Agent String (even though they went to so much trouble to include all the other information in the header), it was blocked.</p>
<p><a href="http://thepizzy.net/blog/wp-content/uploads/2011/01/2011-01-15_1513.png"><img class="aligncenter size-full wp-image-1005" title="Bad Behavior 2" src="http://thepizzy.net/blog/wp-content/uploads/2011/01/2011-01-15_1513.png" alt="" width="948" height="124" /></a></p>
<p>With this image, the plugin saw that the header was missing the &#8220;Accept&#8221; statement, telling the server receiving the request what types of files it was willing to accept as a response. Most of the attempts to bot-post that I have seen blocked in the past week or so have been this type of error.</p>
<p>According to the Bad Behavior <a href="http://bad-behavior.ioerror.us/documentation/benefits/">Benefits and Features page</a>, the plugin runs before any of your PHP-based software (yeah, that&#8217;s right, it is available for any PHP-coded site, not just WordPress blogs), so your server never has to respond to a bot just &#8220;harvesting data and delivering junk.&#8221; Instead the bot is given some 400-style error, and never gets a response from your site.</p>
<p>There are more features and settings that I haven&#8217;t had a chance to play around with yet, but if I find it necessary, I&#8217;ll create an additional post or add them to this one. I recommend this plugin to go alongside any other spam protection you have in place on your form-driven website or blog.</p>

<!-- start wp-tags-to-technorati 1.02 -->

<p class='technorati-tags'>Technorati Tags: <a class='technorati-link' href='http://technorati.com/tag/akismet' rel='tag' target='_blank'>akismet</a>, <a class='technorati-link' href='http://technorati.com/tag/bad+behavior' rel='tag' target='_blank'>bad behavior</a>, <a class='technorati-link' href='http://technorati.com/tag/spam+control' rel='tag' target='_blank'>spam control</a>, <a class='technorati-link' href='http://technorati.com/tag/spam+protection' rel='tag' target='_blank'>spam protection</a>, <a class='technorati-link' href='http://technorati.com/tag/wordpress+plugins' rel='tag' target='_blank'>wordpress plugins</a></p>

<!-- end wp-tags-to-technorati -->
]]></content:encoded>
			<wfw:commentRss>http://thepizzy.net/blog/2011/01/wordpress-plugin-bad-behavior/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Astaro SG &#8220;Joining domain failed&#8221;</title>
		<link>http://thepizzy.net/blog/2010/11/astaro-sg-joining-domain-failed/</link>
		<comments>http://thepizzy.net/blog/2010/11/astaro-sg-joining-domain-failed/#comments</comments>
		<pubDate>Tue, 09 Nov 2010 16:58:43 +0000</pubDate>
		<dc:creator>[[Neo]]</dc:creator>
				<category><![CDATA[How To]]></category>
		<category><![CDATA[Security]]></category>
		<category><![CDATA[Servers]]></category>
		<category><![CDATA[Technology]]></category>
		<category><![CDATA[active directory]]></category>
		<category><![CDATA[ads_get_dnshostname]]></category>
		<category><![CDATA[ads_keytab_add_entry]]></category>
		<category><![CDATA[ASG 120]]></category>
		<category><![CDATA[astaro]]></category>
		<category><![CDATA[astaro sg 120]]></category>
		<category><![CDATA[authentication]]></category>
		<category><![CDATA[can't join domain]]></category>
		<category><![CDATA[clientgen.c:cli_receive_smb]]></category>
		<category><![CDATA[cli_pipe.c:rpc_api_pipe]]></category>
		<category><![CDATA[clock skew too great]]></category>
		<category><![CDATA[Fallback logs]]></category>
		<category><![CDATA[Intrusion Prevention]]></category>
		<category><![CDATA[joining domain failed]]></category>
		<category><![CDATA[Kerberos]]></category>
		<category><![CDATA[pipe \lsarpc fnum]]></category>
		<category><![CDATA[RPC]]></category>
		<category><![CDATA[rpc_client]]></category>
		<category><![CDATA[Samba]]></category>
		<category><![CDATA[SSO astaro]]></category>

		<guid isPermaLink="false">http://thepizzy.net/blog/?p=795</guid>
		<description><![CDATA[I just spent the last 2 business days working on trying to get my Astaro SG 120 v7.507 to re-join the domain, after I deleted the &#8220;computer&#8221; entry from our...]]></description>
			<content:encoded><![CDATA[<p><img class="alignleft size-thumbnail wp-image-812" title="www.astaro.com" src="http://thepizzy.net/blog/wp-content/uploads/2010/11/astaro_logo-150x55.jpg" alt="Astaro Logo" width="150" height="55" />I just spent the last 2 business days working on trying to get my Astaro SG 120 v7.507 to re-join the domain, after I deleted the &#8220;computer&#8221; entry from our Windows 2003 SBS AD. After deleting the computer entry, I rebooted the Astaro box and attempted to join it to the domain (with the same flawless effort I experienced during the initial setup). No luck.</p>
<p>I ran across several Astaro User Forum posts telling people the same things over and over about what to check, and none of it was helping.</p>
<p>I&#8217;ll try and give a run through of some error message appearances from the Fallback error log, and what you should do to fix them. If you have more, leave them in the comments below, and I&#8217;ll add them.</p>
<blockquote><p>ads_get_dnshostname: No dNSHostName attribute!</p></blockquote>
<div id="attachment_798" class="wp-caption aligncenter" style="width: 600px"><a href="http://thepizzy.net/blog/wp-content/uploads/2010/11/2010-11-09_0957.png"><img class="size-full wp-image-798" title="Astaro FQDN Hostname" src="http://thepizzy.net/blog/wp-content/uploads/2010/11/2010-11-09_0957.png" alt="" width="590" height="366" /></a><p class="wp-caption-text">You need to make sure you have a Host Name specified in the FQDN style in the Management &gt; System Settings &gt; Hostname tab</p></div>
<hr />
<blockquote><p>ads_keytab_add_entry: unable to determine machine account&#8217;s dns name in AD</p></blockquote>
<ul>
<li>You need to make sure your Astaro box doesn&#8217;t show up as a Computer listed in Active Directory anywhere there are computers listed, then you need to make sure there is a DNS Host (A) entry for your hostname, and also you need to reboot your Active Directory and/or DNS server. (For me, they were the same Windows SBS Box, but a reboot fixed this error message.)</li>
</ul>
<hr />
<blockquote><p>»clock skew too great«</p></blockquote>
<ul>
<li>You need to make sure the Time &amp; Date on both the Astaro box and the Active Directory server are no more than 5 minutes apart.</li>
</ul>
<hr />
<blockquote><p>»pre-authentication failed«</p></blockquote>
<div id="attachment_804" class="wp-caption aligncenter" style="width: 591px"><a href="http://thepizzy.net/blog/wp-content/uploads/2010/11/2010-11-09_1026.png"><img class="size-full wp-image-804  " title="Single-Sign-On Settings" src="http://thepizzy.net/blog/wp-content/uploads/2010/11/2010-11-09_1026.png" alt="" width="581" height="361" /></a><p class="wp-caption-text">Make sure the Username/Password you&#39;re using to join the domain are correct. They should look like the image above.</p></div>
<hr />
<p>Below is the fix that finally worked for me, but I never saw anything in the User Forums (or anywhere else, for that matter) related to these error codes and the Astaro box (only to Samba and Linux Servers).</p>
<p>&nbsp;</p>
<blockquote><p>libsmb/clientgen.c:cli_receive_smb</p>
<p>rpc_client/cli_pipe.c:rpc_api_pipe</p>
<p>pipe \lsarpc fnum</p></blockquote>
<ul>
<li>This means that the Intrusion Prevention System is preventing the Active Directory server from approving the Active Directory join. You need to create an Exception like this:</li>
</ul>
<div id="attachment_808" class="wp-caption aligncenter" style="width: 644px"><a href="http://thepizzy.net/blog/wp-content/uploads/2010/11/2010-11-09_1032.png"><img class="size-full wp-image-808 " title="Join AD Fix" src="http://thepizzy.net/blog/wp-content/uploads/2010/11/2010-11-09_1032.png" alt="" width="634" height="384" /></a><p class="wp-caption-text">Go to Network Security &gt; Intrusion Prevention &gt; Exceptions and create a new Exception that Skips &quot;Intrusion Prevention&quot; and list the Active Directory Server in the Source Network area.</p></div>
<hr />
<p>I&#8217;m sure there are probably more items in the Fallback error logs that folks have encountered. Surprisingly, I didn&#8217;t even come across <a title="Astaro: Troubleshooting Active Directory" href="https://support.astaro.com/support/images/8/8a/AD_troubleshooting.pdf" target="_blank">this PDF document</a> detailing a lot of them during my searches until I was researching the error codes for this post. Check that document out and see if your answer is in there.</p>
<p>&nbsp;</p>
<p>The main rebuttals from most of the &#8220;suggestions&#8221; you&#8217;ll find on the User Forums are:</p>
<ol>
<li>You <strong>don&#8217;t</strong> need to create a Pre-Win2000 Computer in Active Directory for this to work.</li>
<li>You <strong>can&#8217;t</strong> have an existing computer entry in Active Directory for the hostname you&#8217;ve given your Astaro box.</li>
<li>You <strong>should</strong> create a DNS Host (A) entry for the Astaro box, if you run a DNS server outside of the Astaro box</li>
<li>The Time &amp; Date on both the Server and Astaro Box <strong>need to be</strong> within 5 minutes of each other.</li>
<li>You <strong>don&#8217;t</strong> have to be able to ping the Astaro box from the server for this to work.</li>
<li>You <strong>do have to</strong> be able to ping the Active Directory server from the Astaro box&#8217;s Support &gt; Tools area</li>
<li>Domains ending in .local <strong>will work</strong>.</li>
<li>You <strong>don&#8217;t have to</strong> use all CAPS when filling in the hostname  &amp; domain name, but it&#8217;s suggested by the Astaro people. It won&#8217;t make a difference to DNS &#8211; CAPS or lowercase both resolve the same.</li>
</ol>
<p>As I mentioned above, if you have any other error messages or tips or suggestions, etc., related to getting the Astaro box on the domain, please post them in the comments. Too many people have spent too long trying to get things to work simply because the information wasn&#8217;t out there when they were searching.</p>

<!-- start wp-tags-to-technorati 1.02 -->

<p class='technorati-tags'>Technorati Tags: <a class='technorati-link' href='http://technorati.com/tag/active+directory' rel='tag' target='_blank'>active directory</a>, <a class='technorati-link' href='http://technorati.com/tag/ads_get_dnshostname' rel='tag' target='_blank'>ads_get_dnshostname</a>, <a class='technorati-link' href='http://technorati.com/tag/ads_keytab_add_entry' rel='tag' target='_blank'>ads_keytab_add_entry</a>, <a class='technorati-link' href='http://technorati.com/tag/ASG+120' rel='tag' target='_blank'>ASG 120</a>, <a class='technorati-link' href='http://technorati.com/tag/astaro' rel='tag' target='_blank'>astaro</a>, <a class='technorati-link' href='http://technorati.com/tag/astaro+sg+120' rel='tag' target='_blank'>astaro sg 120</a>, <a class='technorati-link' href='http://technorati.com/tag/authentication' rel='tag' target='_blank'>authentication</a>, <a class='technorati-link' href='http://technorati.com/tag/can%27t+join+domain' rel='tag' target='_blank'>can't join domain</a>, <a class='technorati-link' href='http://technorati.com/tag/clientgen.c%3Acli_receive_smb' rel='tag' target='_blank'>clientgen.c:cli_receive_smb</a>, <a class='technorati-link' href='http://technorati.com/tag/cli_pipe.c%3Arpc_api_pipe' rel='tag' target='_blank'>cli_pipe.c:rpc_api_pipe</a>, <a class='technorati-link' href='http://technorati.com/tag/clock+skew+too+great' rel='tag' target='_blank'>clock skew too great</a>, <a class='technorati-link' href='http://technorati.com/tag/Fallback+logs' rel='tag' target='_blank'>Fallback logs</a>, <a class='technorati-link' href='http://technorati.com/tag/Intrusion+Prevention' rel='tag' target='_blank'>Intrusion Prevention</a>, <a class='technorati-link' href='http://technorati.com/tag/joining+domain+failed' rel='tag' target='_blank'>joining domain failed</a>, <a class='technorati-link' href='http://technorati.com/tag/Kerberos' rel='tag' target='_blank'>Kerberos</a>, <a class='technorati-link' href='http://technorati.com/tag/pipe+%5Clsarpc+fnum' rel='tag' target='_blank'>pipe \lsarpc fnum</a>, <a class='technorati-link' href='http://technorati.com/tag/RPC' rel='tag' target='_blank'>RPC</a>, <a class='technorati-link' href='http://technorati.com/tag/rpc_client' rel='tag' target='_blank'>rpc_client</a>, <a class='technorati-link' href='http://technorati.com/tag/Samba' rel='tag' target='_blank'>Samba</a>, <a class='technorati-link' href='http://technorati.com/tag/SSO+astaro' rel='tag' target='_blank'>SSO astaro</a></p>

<!-- end wp-tags-to-technorati -->
]]></content:encoded>
			<wfw:commentRss>http://thepizzy.net/blog/2010/11/astaro-sg-joining-domain-failed/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Thoughts on tsn, and possible changes</title>
		<link>http://thepizzy.net/blog/2010/10/thoughts-on-tsn-and-possible-changes/</link>
		<comments>http://thepizzy.net/blog/2010/10/thoughts-on-tsn-and-possible-changes/#comments</comments>
		<pubDate>Mon, 11 Oct 2010 15:10:52 +0000</pubDate>
		<dc:creator>[[Neo]]</dc:creator>
				<category><![CDATA[Projects]]></category>
		<category><![CDATA[Technology]]></category>
		<category><![CDATA[the-blot.net]]></category>
		<category><![CDATA[the-spot.net]]></category>
		<category><![CDATA[The-Spot.Network]]></category>
		<category><![CDATA[diaspora]]></category>
		<category><![CDATA[podcasts]]></category>
		<category><![CDATA[Servers]]></category>
		<category><![CDATA[social networks]]></category>

		<guid isPermaLink="false">http://thepizzy.net/blog/?p=786</guid>
		<description><![CDATA[I&#8217;ve run an online community for nearly a decade now &#8211; and many spin-offs and other projects &#38; even job opportunities have been the result of what I&#8217;ve learned while...]]></description>
			<content:encoded><![CDATA[<div id="attachment_787" class="wp-caption alignright" style="width: 310px"><img class="size-medium wp-image-787" title="Dandelion Seeds" src="http://thepizzy.net/blog/wp-content/uploads/2010/10/dandelion_seeds_being_blown1-300x199.jpg" alt="" width="300" height="199" /><p class="wp-caption-text">Credit: Paul Mutton</p></div>
<p>I&#8217;ve run an online community for nearly a decade now &#8211; and many spin-offs and other projects &amp; even job opportunities have been the result of what I&#8217;ve learned while working on my websites.</p>
<p>I started everything when I was 18, with the help of a few friends in the college dorms at ETBU back in 2001, and from there things grew exponentially by word of mouth, until at its peak we had most of Nacogdoches High School in Nacogdoches, TX on the website. There were users in  about 7 different countries, all over the United States, and it was the start of the Social Networking concept.</p>
<p>Myspace came along, and then Facebook, and now things have slowed down quite a bit, as everyone has grown up and moved on with their life. The site is still home to a dedicated few that host their Journals there (which we started before the invention of blogging software).</p>
<p>But I find myself less and less interested in keeping up with it &#8211; and it&#8217;s a little sad after all thoughts I&#8217;ve posted on it, the ideas that others have contributed that changed the course of my life, all the long nights writing code, and just many days at work coming up with ideas &amp; features. That huge time investment is also the reason I&#8217;m not all that crazy about re-investing so much time into getting it going again.</p>
<p>The site was cutting edge for its time, and we were on the forefront of the popular technologies before they were popular (video casts, podcasts, internet radio, blogging, social networking, etc). It was quite literally The Spot you wanted to be, and we put a lot of effort into making the atmosphere of the community match that branding.</p>
<p>These days I&#8217;m interested in learning new things (as many of the old things I&#8217;ve built most of my sites around are being phased out). Myspace is all but gone from the minds of many internet socialites, and Facebook is reaching its Myspace pinnacle. In another 2 years, it will have gone by the wayside just as Myspace did. Twitter is also growing much faster than it expected, and as it keeps evolving out of what it originally was by adding new features, the simplicity of its design will live on, but in another application most likely.</p>
<p>As such, I&#8217;m considering finally implementing a domain I&#8217;ve held on to for a long time &#8211; the-blot.net, and the-blot.com &#8211; which were originally intended to be a one-stop blogging service where you can post to any of your blogs, and also read from any of your friends blogs all in one place. That idea was solved in part by Google Reader and Ping.fm&#8217;s posting abilities.</p>
<p>So instead of making it just about your blogs, I am going to grab the alpha version of the <a href="http://www.joindiaspora.com/" target="_blank">Diaspora project</a> and start up another social networking site to see what kinds of technology are being implemented in the next generation of social clustering sites. I&#8217;m going to have to build a new Linux server &amp; redirect my domains, as well as compile their website codes, so all of this could take a while (as I have to salvage several different computer parts for the server). But as I transition to new technologies, I&#8217;ll keep track of the changes here, just as I did when I upgraded the-spot.net from the early days of the static html tsnII to the cutting edge dynamic tsnIII back in 2004.</p>

<!-- start wp-tags-to-technorati 1.02 -->

<p class='technorati-tags'>Technorati Tags: <a class='technorati-link' href='http://technorati.com/tag/diaspora' rel='tag' target='_blank'>diaspora</a>, <a class='technorati-link' href='http://technorati.com/tag/podcasts' rel='tag' target='_blank'>podcasts</a>, <a class='technorati-link' href='http://technorati.com/tag/Servers' rel='tag' target='_blank'>Servers</a>, <a class='technorati-link' href='http://technorati.com/tag/social+networks' rel='tag' target='_blank'>social networks</a>, <a class='technorati-link' href='http://technorati.com/tag/the-blot.net' rel='tag' target='_blank'>the-blot.net</a>, <a class='technorati-link' href='http://technorati.com/tag/the-spot.net' rel='tag' target='_blank'>the-spot.net</a></p>

<!-- end wp-tags-to-technorati -->
]]></content:encoded>
			<wfw:commentRss>http://thepizzy.net/blog/2010/10/thoughts-on-tsn-and-possible-changes/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Hamachi Web Status Images</title>
		<link>http://thepizzy.net/blog/2009/09/hamachi-web-status-images/</link>
		<comments>http://thepizzy.net/blog/2009/09/hamachi-web-status-images/#comments</comments>
		<pubDate>Thu, 17 Sep 2009 16:05:13 +0000</pubDate>
		<dc:creator>[[Neo]]</dc:creator>
				<category><![CDATA[How To]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[Projects]]></category>
		<category><![CDATA[Technology]]></category>
		<category><![CDATA[tsnLocal.net]]></category>
		<category><![CDATA[hamachi]]></category>
		<category><![CDATA[images]]></category>
		<category><![CDATA[status]]></category>
		<category><![CDATA[vpn]]></category>
		<category><![CDATA[Web]]></category>

		<guid isPermaLink="false">http://thepizzy.net/blog/?p=474</guid>
		<description><![CDATA[Update&#8230; Unfortunately, LogMeIn figured out they forgot about that page, I guess when people started reading this post and hitting it on their servers. They have removed the text status...]]></description>
			<content:encoded><![CDATA[<h2>Update&#8230;</h2>
<p>Unfortunately, LogMeIn figured out they forgot about that page, I guess when people started reading this post and hitting it on their servers. They have removed the text status as well as all the others, and I can&#8217;t figure out why they would do such a thing.</p>
<p>I&#8217;m also not sure what they&#8217;re offering as an alternative either. So if you know, please leave a comment below. Thanks.</p>
<h2>Depreciated Process&#8230;</h2>
<p><img class="alignleft size-full wp-image-628" title="LogMeIn Hamachi Logo" src="http://thepizzy.net/blog/wp-content/uploads/2009/09/hamachi1.jpg" alt="" width="384" height="189" />A while back, I started a project called <a href="http://thepizzy.net/blog/?s=tsnlocal">tsn.lcl or tsnlocal</a>, but gave up on it when my electricity bill hit $400 in a month.</p>
<p>Today, I decided to fix up the domain name and get it back on the internet &#8211; at least to remove it from GoDaddy&#8217;s Parking Page &#8211; where they&#8217;re making money, not me, off of it.</p>
<p>When I got it <a href="http://tsnlocal.net" target="_blank">published</a> I noticed that none of the Hamachi Web Status images worked anymore, and that the <a href="https://my.hamachi.cc/status/image.php?5.28.161.250">link to such an image</a>, redirected to their login page for your Hamachi Management Dashboard. However, upon further investigation, I found that there was not only an Image version of those status instances, but also a <a href="https://my.hamachi.cc/status/text.php?5.28.161.250">text version</a>.</p>
<p>I really wanted to show the online status of all my machines again, so I wrote my own php script to parse that text data, and created some simple images to show on the website based on the returned status.</p>
<p>So here&#8217;s the code so you can do the same thing&#8230;</p>
<h2>The PHP Function</h2>
<p>{code type=php}&lt;?php<br />
function hamachiImg($ip) {<br />
$url = &#8220;https://my.hamachi.cc/status/text.php?$ip&#8221;;<br />
$status = file_get_contents($url);<br />
$status = preg_replace(&#8216;/\d*\.\d*\.\d*.\d* /&#8217;, &#8221;, $status);<br />
$image_url = &#8220;./images/$status.png&#8221;;<br />
return $image_url;<br />
}<br />
?&gt;{/code}<br />
This code creates a $url variable with the address to the text status, based on the $ip that is passed to it. Then it requests the data, removes the ip address and the trailing space, leaving only the status text. On the server, I have a collection of images with the 4 different statuses as their file name, and with that an $image_url is created to be returned.</p>
<p>The 4 possible statuses are:</p>
<ul>
<li><img class="alignnone" title="hamachi-online" src="http://tsnlocal.net/images/online.png" alt="" width="16" height="17" /> &#8211; online</li>
<li><img class="alignnone" title="hamachi-offline" src="http://tsnlocal.net/images/offline.png" alt="" width="16" height="17" /> &#8211; offline</li>
<li><img class="alignnone" title="hamachi-unknown" src="http://tsnlocal.net/images/unknown.png" alt="" width="16" height="17" /> &#8211; unknown</li>
<li><img class="alignnone" title="hamachi-error" src="http://tsnlocal.net/images/error.png" alt="" width="16" height="17" /> &#8211; error</li>
</ul>
<h2>The HTML Code and PHP Function Call</h2>
<p>Once you have your php function in the page (I stuck mine before the first &lt;html&gt; tag), you can use the php function to insert the image url when you pass it an IP&#8230;<br />
{code type=html}&lt;table&gt;<br />
&lt;tr&gt;<br />
&lt;td style=&#8221;width: 100%&#8221;&gt;[[Neo]]:&lt;/td&gt;<br />
&lt;td style=&#8221;width: 100%&#8221;&gt; &lt;img src=&#8221;&lt;?php echo hamachiImg(&#8217;5.37.117.104&#8242;); ?&gt;&#8221;&gt;&lt;/td&gt;<br />
&lt;/tr&gt;<br />
&lt;/table&gt;{/code}<br />
<a href="http://thepizzy.net/blog/wp-content/uploads/2009/09/hamachi-example.png"><img class="alignright size-full wp-image-477" title="hamachi-example" src="http://thepizzy.net/blog/wp-content/uploads/2009/09/hamachi-example.png" alt="hamachi-example" width="210" height="201" /></a>Once you&#8217;ve done that, assuming you have entered a valid hamachi IP address, the results should look something like the image at right.</p>

<!-- start wp-tags-to-technorati 1.02 -->

<p class='technorati-tags'>Technorati Tags: <a class='technorati-link' href='http://technorati.com/tag/hamachi' rel='tag' target='_blank'>hamachi</a>, <a class='technorati-link' href='http://technorati.com/tag/images' rel='tag' target='_blank'>images</a>, <a class='technorati-link' href='http://technorati.com/tag/status' rel='tag' target='_blank'>status</a>, <a class='technorati-link' href='http://technorati.com/tag/vpn' rel='tag' target='_blank'>vpn</a>, <a class='technorati-link' href='http://technorati.com/tag/Web' rel='tag' target='_blank'>Web</a></p>

<!-- end wp-tags-to-technorati -->
]]></content:encoded>
			<wfw:commentRss>http://thepizzy.net/blog/2009/09/hamachi-web-status-images/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Dallas Stars Twitter (@dallasstars and @thedallasstars)</title>
		<link>http://thepizzy.net/blog/2009/05/dallas-stars-twitter/</link>
		<comments>http://thepizzy.net/blog/2009/05/dallas-stars-twitter/#comments</comments>
		<pubDate>Tue, 12 May 2009 04:18:13 +0000</pubDate>
		<dc:creator>[[Neo]]</dc:creator>
				<category><![CDATA[Projects]]></category>
		<category><![CDATA[Technology]]></category>
		<category><![CDATA[Twitter]]></category>
		<category><![CDATA[cfaulk]]></category>
		<category><![CDATA[dallas stars]]></category>
		<category><![CDATA[dallas stars twitter]]></category>
		<category><![CDATA[dallasstars]]></category>
		<category><![CDATA[neotsn]]></category>
		<category><![CDATA[shickdog]]></category>
		<category><![CDATA[thedallasstars]]></category>
		<category><![CDATA[twitter]]></category>
		<category><![CDATA[winkydo]]></category>

		<guid isPermaLink="false">http://thepizzy.net/blog/?p=408</guid>
		<description><![CDATA[What happened to the Dallas Stars Twitter? They removed me from their friend list, and changed everything! If you&#8217;re asking yourself that question&#8230;it&#8217;s not what you think. Here&#8217;s what happened...]]></description>
			<content:encoded><![CDATA[<p><strong><img class="alignleft" title="@thedallasstars" src="http://a1.twimg.com/profile_images/421667289/stars-logo.png" alt="" width="200" height="200" />What happened to the Dallas Stars Twitter? They removed me from their friend list, and changed everything!</strong></p>
<p>If you&#8217;re asking yourself that question&#8230;it&#8217;s not what you think. Here&#8217;s what happened &#8211; it was all a mistake&#8230;</p>
<h3>The Backstory&#8230;</h3>
<p>Back in the Fall of 2007, @<a href="http://twitter.com/winkydo">winkydo</a> had an idea to start broadcasting the scores during the Dallas Stars NHL hockey games. <span id="more-408"></span>So he went to register the account for @<a href="http://twitter.com/dallasstars">DallasStars</a> and from then on, he and I (@<a href="http://twitter.com/neotsn">neotsn</a>) were all about posting updates, tying in news feeds. Our updates got pretty complicated using a 1400-character if-statement to parse a collection of inputs and derived values from a database of all the NHL players, their numbers and their teams. We&#8217;d watch every game, intently focused on a 52&#8243; Plasma HD TV so that we could see which players scored, which assissted, and get all the stats up on the internet before the official NHL Game Stats page was updated &#8211; and often before the announcers could say.</p>
<p>Well, that lasted all the way until the end of 2008-09 Season.</p>
<p>We got a message from @<a href="http://twitter.com/cfaulk">cfaulk</a>, asking who was behind the @<a href="http://twitter.com/dallasstars">DallasStars</a>, but because we had hidden who was behind the account, and had a policy never to reply, opinionate, or follow people with that account, we did not respond. Unfortunately, the means that @<a href="http://twitter.com/cfaulk">cfaulk</a> couldn&#8217;t find us to contact us.</p>
<p>Why does it matter that @<a href="http://twitter.com/cfaulk">cfaulk</a> couldn&#8217;t find us? Because he&#8217;s the Sr. VP of Ticket Sales for the @<a href="http://twitter.com/dallasstars">DallasStars</a>, Sr. Acct Executive for the Texas Rangers, and the Acct Executive for the Dallas Burn.</p>
<h3>What happened&#8230;</h3>
<p>Well, while the Dallas Stars organization was trying to get information from Twitter Co. about who was running the site, they created @<a href="http://twitter.com/thedallasstars">TheDallasStars</a> to start their feed. All they wanted to do was ask us to remove the word &#8220;Official&#8221; from our description since there was truely an Official feed out there.</p>
<p>&#8230;But they never got a response from the Twitter people.</p>
<p>Meanwhile, I saw the advertisement on Facebook for @<a href="http://twitter.com/thedallasstars">TheDallasStars</a> as the &#8220;Official&#8221; Twitter feed for the Dallas Stars, and made a comment advertising the one we set up. Then I went to look into the <a href="http://dallasstars.com">DallasStars.com</a> website, and in their Fan Zone menu, and pulled up their <a href="http://www.facebook.com/pages/Dallas-TX/Official-Dallas-Stars/47901465214">Official Facebook Fanpage</a> &#8211; it was the same one. So then I went back to figure out who it was that asked the @<a href="http://twitter.com/dallasstars">DallasStars</a> who they were, and found it was @<a href="http://twitter.com/cfaulk">cfaulk</a> and found him on LinkedIn, figured out who he was there, and asked him to confirm it. He responded asking who I was, and I gave him my contact info, explained how we were using the @<a href="http://twitter.com/dallasstars">DallasStars</a> profile, but didn&#8217;t hear anything back</p>
<h3>Then, today&#8230;</h3>
<p>When @<a href="http://twitter.com/cfaulk">cfaulk</a> and company logged into their Twitter account, they noticed that all-the-sudden, the account they registered (@<a href="http://twitter.com/thedallasstars">TheDallasStars</a>) was now simply @<a href="http://twitter.com/dallasstars">DallasStars</a>. So I got an email from @<a href="http://twitter.com/cfaulk">cfaulk</a> asking to talk to us. I went and looked at the @<a href="http://twitter.com/dallasstars">DallasStars</a> page to find out it had been suspended as @<a href="http://twitter.com/dallasstars_I">DallasStars_I</a>. So we were concerned too, because we had hoped we could transfer the fanbase to the NHL Organization by simply turning over the account credentials to the Dallas Stars Organization, as well as the infrastructure we had developed&#8230;and possibly work out some kind of contract-labor situation where we could keep maintaining it for them.</p>
<p>This evening there was a conference call placed between @<a href="http://twitter.com/winkydo">winkydo</a>, @<a href="http://twitter.com/cfaulk">cfaulk</a>, @<a href="http://twitter.com/shickdog">shickdog</a> (Sr. Dir. of Communications) and myself (@<a href="http://twitter.com/neotsn">neotsn</a>). During our conversation, we discovered that @<a href="http://twitter.com/cfaulk">cfaulk</a> &amp; @<a href="http://twitter.com/shickdog">shickdog</a> thought we ditched the account; and @<a href="http://twitter.com/winkydo">winkydo</a> and I thought they had acquired the account. But apparently Twitter did it on their own accord, probably to reduce mitigation, and just hand over the account to the copyright holder.</p>
<p>We were all disappointed by this because we lost the fanbase we had gained over the 1.5 seasons of tweeting. However, that&#8217;s part of the fun &#8211; and we still have 2400 (of the 2538 followers) emails telling us who is following. So we can re-add everyone as time goes by, a couple each day so we don&#8217;t get banned for adding disproportionate amounts of followers.</p>
<p>Essentially all they wanted to get in touch with us for was to ask us to remove the &#8220;Official&#8221; verbiage from the description on our page. They were happy that we had such enthusiasm and wanted to remain in touch, since they were just getting started in all of this social networking, and we were able to acquire the fans without their media presence.</p>
<h3>Here&#8217;s The Breakdown&#8230;</h3>
<p>Now we have new accounts set up, and they all have purposes, and @<a href="http://twitter.com/winkydo">winkydo</a> and I are going to be working closely with @<a href="http://twitter.com/cfaulk">cfaulk</a> &amp; @<a href="http://twitter.com/shickdog">shickdog</a> to get all this up and running again. At least, that&#8217;s the hope I think everyone had when we ended the conference call.</p>
<p>Here&#8217;s the twitter accounts that came out of it, and what they are:</p>
<ul>
<li><strong><span style="color: #00ff00;">@<a href="http://twitter.com/DallasStars">DallasStars</a> &#8211; The Official Dallas Stars Twitter account (formerly @thedallasstars)</span></strong>
<ul>
<li>Follow this acct to get <strong>Official News</strong> from the Dallas Stars Organization</li>
<li>Updated and maintained by the Dallas Stars NHL Organization&#8217;s Communications Department</li>
</ul>
</li>
<li><strong><span style="color: #00ff00;">@<a href="http://twitter.com/TheDallasStars">TheDallasStars</a> &#8211; The Fan-version Dallas Stars Twitter account (formerly @dallasstars)</span></strong>
<ul>
<li>Follow this acct to get most of the <strong>Official News, the Popular Stars Blogs, and Live Scores</strong></li>
<li>Yes, we did clear it with @<a href="http://twitter.com/cfaulk">cfaulk</a> that it would be OK with them to re-register @thedallasstars since they had our original page.</li>
<li>Updated and maintained by @<a href="http://twitter.com/winkydo">winkydo</a> and @<a href="http://twitter.com/neotsn">neotsn</a>, with Live Scores and News feeds just like before. The same Dallas Stars feed/speed you loved for the past 2 seasons, but this time, you know who&#8217;s doing it.</li>
</ul>
</li>
<li><strong><span style="color: #00ff00;">@<a href="http://twitter.com/DallasStarsLive">DallasStarsLive</a> &#8211; A new Fan-version of the Dallas Stars Twitter account</span></strong>
<ul>
<li>This is <strong>ONLY Live Scores</strong> updated during the games by @<a href="http://twitter.com/winkydo">winkydo</a> and @<a href="http://twitter.com/neotsn">neotsn</a>.</li>
</ul>
</li>
</ul>
<p><strong><span style="color: #ff0000;">Please ReTweet this, and tell all your friends about this change &#8211; so everyone can hit the ground running next season!</span></strong></p>

<!-- start wp-tags-to-technorati 1.02 -->

<p class='technorati-tags'>Technorati Tags: <a class='technorati-link' href='http://technorati.com/tag/cfaulk' rel='tag' target='_blank'>cfaulk</a>, <a class='technorati-link' href='http://technorati.com/tag/dallas+stars' rel='tag' target='_blank'>dallas stars</a>, <a class='technorati-link' href='http://technorati.com/tag/dallas+stars+twitter' rel='tag' target='_blank'>dallas stars twitter</a>, <a class='technorati-link' href='http://technorati.com/tag/dallasstars' rel='tag' target='_blank'>dallasstars</a>, <a class='technorati-link' href='http://technorati.com/tag/neotsn' rel='tag' target='_blank'>neotsn</a>, <a class='technorati-link' href='http://technorati.com/tag/shickdog' rel='tag' target='_blank'>shickdog</a>, <a class='technorati-link' href='http://technorati.com/tag/thedallasstars' rel='tag' target='_blank'>thedallasstars</a>, <a class='technorati-link' href='http://technorati.com/tag/twitter' rel='tag' target='_blank'>twitter</a>, <a class='technorati-link' href='http://technorati.com/tag/winkydo' rel='tag' target='_blank'>winkydo</a></p>

<!-- end wp-tags-to-technorati -->
]]></content:encoded>
			<wfw:commentRss>http://thepizzy.net/blog/2009/05/dallas-stars-twitter/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>TweetSuite, TweetBacks, and Ping.fm WordPress plugin (Update)</title>
		<link>http://thepizzy.net/blog/2009/04/tweetsuite-tweetbacks-and-pingfm-wordpress-plugin-update/</link>
		<comments>http://thepizzy.net/blog/2009/04/tweetsuite-tweetbacks-and-pingfm-wordpress-plugin-update/#comments</comments>
		<pubDate>Wed, 01 Apr 2009 14:34:23 +0000</pubDate>
		<dc:creator>[[Neo]]</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[Projects]]></category>
		<category><![CDATA[Technology]]></category>
		<category><![CDATA[TweetSuite]]></category>
		<category><![CDATA[Updates]]></category>
		<category><![CDATA[api]]></category>
		<category><![CDATA[code]]></category>
		<category><![CDATA[database]]></category>
		<category><![CDATA[MySQL]]></category>
		<category><![CDATA[Ping.fm]]></category>
		<category><![CDATA[plugin]]></category>
		<category><![CDATA[tweetback]]></category>
		<category><![CDATA[tweetbacks]]></category>
		<category><![CDATA[webhost]]></category>
		<category><![CDATA[Wordpress]]></category>

		<guid isPermaLink="false">http://thepizzy.net/blog/?p=356</guid>
		<description><![CDATA[Well, I sent off my plugin code to Dan Zarrella, and got the Ping.fm developers API Key approved, and got WordPress.org to approve the plugin, and have been running it...]]></description>
			<content:encoded><![CDATA[<p><img class="alignleft" title="Twitter Logo" src="https://s3.amazonaws.com/twitter_production/profile_images/1125794203/at-twitter.png" alt="" width="128" height="128" />Well, I sent off my plugin code to Dan Zarrella, and got the Ping.fm developers API Key approved, and got WordPress.org to approve the plugin, and have been running it on my blog since its original announcement &#8211; but have run into a possible issue&#8230;</p>
<p>My webhost says it is creating a lot of &#8220;sleeper&#8221; processes on the database server, and using up a lot of the processor resources. My account was even suspended until I fixed it.</p>
<p>SO &#8211; I am going to be rewriting the whole thing, pretty much from scratch now, and it will only be loosely based on Dan&#8217;s version&#8230; <span id="more-356"></span></p>
<p>Currently, the code will run through the database of posts, and find those that have shortened URLs stored for them, run a twitter search, and return/parse/store/display the resulting tweetbacks. And it does this every 5 minutes.</p>
<p>However, that sucks up a lot of processing power to do that, especially if you have a big blog, popular blog, or both. The Answer: A Rewrite. This one is going to run a single Twitter search for every shortened url in the database, return ALL the results once, and parse them out, store them in the database, and associate them to their respective parent posts.</p>
<p>So, there&#8217;s the update for why this hasn&#8217;t been released yet.</p>
<p>I&#8217;m also working on trying to get the retro-active TweetThis buttons working on old posts &#8211; but something isn&#8217;t working right &#8211; either it&#8217;s the original code that isn&#8217;t comparing what&#8217;s in the database to the conditional statement correctly (if <em>this.url</em> = &#8220;&#8221;, then <em>make new ones</em>), or something. It&#8217;s going to take some more testing on my own test database, since my webhost is getting antsy with all the processes I&#8217;m using.</p>
<p>I&#8217;ll keep everyone updated as it moves along. Thanks.<br />
<a href="http://twitter.com/neotsn"><img class="size-full wp-image-583  aligncenter" title="twitter.com/neotsn" src="http://thepizzy.net/blog/wp-content/uploads/2010/08/twitter-wordpress-neo12.png" alt="twitter.com/neotsn" width="350" height="125" /></a></p>

<!-- start wp-tags-to-technorati 1.02 -->

<p class='technorati-tags'>Technorati Tags: <a class='technorati-link' href='http://technorati.com/tag/api' rel='tag' target='_blank'>api</a>, <a class='technorati-link' href='http://technorati.com/tag/code' rel='tag' target='_blank'>code</a>, <a class='technorati-link' href='http://technorati.com/tag/database' rel='tag' target='_blank'>database</a>, <a class='technorati-link' href='http://technorati.com/tag/MySQL' rel='tag' target='_blank'>MySQL</a>, <a class='technorati-link' href='http://technorati.com/tag/Ping.fm' rel='tag' target='_blank'>Ping.fm</a>, <a class='technorati-link' href='http://technorati.com/tag/plugin' rel='tag' target='_blank'>plugin</a>, <a class='technorati-link' href='http://technorati.com/tag/Programming' rel='tag' target='_blank'>Programming</a>, <a class='technorati-link' href='http://technorati.com/tag/tweetback' rel='tag' target='_blank'>tweetback</a>, <a class='technorati-link' href='http://technorati.com/tag/tweetbacks' rel='tag' target='_blank'>tweetbacks</a>, <a class='technorati-link' href='http://technorati.com/tag/TweetSuite' rel='tag' target='_blank'>TweetSuite</a>, <a class='technorati-link' href='http://technorati.com/tag/webhost' rel='tag' target='_blank'>webhost</a>, <a class='technorati-link' href='http://technorati.com/tag/Wordpress' rel='tag' target='_blank'>WordPress</a></p>

<!-- end wp-tags-to-technorati -->
]]></content:encoded>
			<wfw:commentRss>http://thepizzy.net/blog/2009/04/tweetsuite-tweetbacks-and-pingfm-wordpress-plugin-update/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>TweetSuite WordPress Plugin + Ping.fm (Preview)</title>
		<link>http://thepizzy.net/blog/2009/03/tweetsuite-wordpress-plugin-pingfm-preview/</link>
		<comments>http://thepizzy.net/blog/2009/03/tweetsuite-wordpress-plugin-pingfm-preview/#comments</comments>
		<pubDate>Sat, 21 Mar 2009 16:41:23 +0000</pubDate>
		<dc:creator>[[Neo]]</dc:creator>
				<category><![CDATA[Ping.fm]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[Projects]]></category>
		<category><![CDATA[Technology]]></category>
		<category><![CDATA[Thought Experiments]]></category>
		<category><![CDATA[TweetSuite]]></category>
		<category><![CDATA[Twitter]]></category>
		<category><![CDATA[Wordpress]]></category>
		<category><![CDATA[beta]]></category>
		<category><![CDATA[dan zarrella]]></category>
		<category><![CDATA[database]]></category>
		<category><![CDATA[internet]]></category>
		<category><![CDATA[MySQL]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[site]]></category>
		<category><![CDATA[syndication]]></category>
		<category><![CDATA[tweetbacks]]></category>
		<category><![CDATA[twitter]]></category>

		<guid isPermaLink="false">http://thepizzy.net/blog/?p=319</guid>
		<description><![CDATA[A couple weeks ago, I found out that Twitter had a Search feature that showed real-time tweets for a keyword. I gave it a little thought, considered what it would...]]></description>
			<content:encoded><![CDATA[<p>A couple weeks ago, I found out that <a href="http://twitter.com" target="_blank">Twitter</a> had a <a href="http://search.twitter.com" target="_blank">Search feature</a> that showed real-time tweets for a keyword. I gave it a little thought, considered what it would take to actually write the software &#8211; and then wised up, and decided to see if someone already did the hard work.</p>
<p>Sure enough, <a title="@danzarrella" href="http://twitter.com/danzarrella" target="_blank">Dan Zarrella</a> over at <a href="http://danzarrella.com/" target="_blank">danzarrella.com</a> had. He wrote one for <a href="http://danzarrella.com/tweetbacks-beta.html" target="_blank">Tweetbacks</a>, and then expanded on it with <a href="http://danzarrella.com/beyond-tweetbacks-introducing-tweetsuite.html" target="_blank">TweetSuite</a>. So I gave them a shot.</p>
<p>I started with Tweetbacks on the <a href="http://freeformfrog.com/blog" target="_blank">FreeformFrog.com Blog</a> and everything seemed to be working fine &#8211; until one day when the Tweetbacks stopped. It just stopped finding them &#8211; even though I knew they were getting tweeted &#8211; because I was using <a href="http://ping.fm" target="_blank">Ping.fm</a> to syndicate my blog posts to the appropriate social networks.</p>
<p>I gave it a couple weeks, and then decided I was going to fix it. I was tired of not having my TweetBacks working &#8211; especially during my efforts pushing a Social Networking campaign at job.</p>
<p>So, I added @danzarrella, and asked&#8230;</p>
<blockquote><p><span class="entry-content">@<a href="http://twitter.com/danzarrella">danzarrella</a> do you have plans to integrate ping.fm posting in TweetSuite? If not, mind if I take a crack at it?<br />
from @neotsn at <a class="entry-date" rel="bookmark" href="http://twitter.com/neotsn/status/1350750034"><span class="published">4:32 PM Mar 18th</span></a> from web</span></p></blockquote>
<p><span class="entry-content">A few minutes later, I got a response&#8230;</span></p>
<blockquote><p><span class="entry-content"><span class="entry-content">@<a href="http://twitter.com/neotsn">neotsn</a> go to town<br />
from @danzarrella at </span><span class="meta entry-meta"><a class="entry-date" rel="bookmark" href="http://twitter.com/danzarrella/status/1350761852"><span class="published">4:34 PM Mar 18th</span></a> from <a href="http://www.tweetdeck.com/">TweetDeck</a> <a href="http://twitter.com/neotsn/status/1350750034">in reply to neotsn</a></span></span></p></blockquote>
<p><span class="entry-content"><span class="meta entry-meta">Excellent&#8230;now I had his blessing to hack his codes. And so I have&#8230;<br />
</span></span></p>
<p><span class="entry-content"><span class="meta entry-meta"><span id="more-319"></span><br />
</span></span></p>
<h2><span class="entry-content"><span class="meta entry-meta">The download is coming soon</span></span></h2>
<h3><span class="entry-content"><span class="meta entry-meta">I have to get my Ping.fm API Key approved before anyone but me can install the plugin.<br />
</span></span></h3>
<p><span class="entry-content"><span class="meta entry-meta">And now I present to you a general overview of what I wanted to accomplish, and how I did it. (<strong>Please note, this is a GENERAL overview with some examples</strong> &#8211; it&#8217;s not meant to be a how-to, so don&#8217;t try to just copy/paste the samples &#8211; there is much more to do than can be explained here). Let&#8217;s get started&#8230;</span></span></p>
<h2><span class="entry-content"><span class="meta entry-meta">Objectives&#8230;</span></span></h2>
<ol>
<li><span style="text-decoration: underline;"><strong>Make it post through Ping.fm</strong></span> &#8211; I syndicate all my stuff through <a href="http://twitterfeed.com" target="_blank">twitterfeed.com</a> and it pushes everything out through Ping.fm for me. Upon further investigation, I noticed that TweetSuite used its own publishing code to push out the updates &#8211; after it created its own shortened urls and attached them. So of course it would never find my updates &#8211; it didn&#8217;t know what urls to search for, because it didn&#8217;t create them.</li>
<li><span style="text-decoration: underline;"><strong>Make it find my tweets that were pushed through Ping.fm</strong></span> &#8211; After realizing that it stopped searching for blog titles and started searching for the shortened urls as the unique identifier on the web, I realized that I needed it to create my urls and push them out with my Ping.fm update text. That was the only way to let TweetSuite know that there were tweets out there about my blog, and obtw here&#8217;s the link.</li>
<li><span style="text-decoration: underline;"><strong>Clean up some of the things that were a little messy</strong></span> &#8211; Once I got poking around in the code, I noticed that it some parts of it were written a little redundantly, and in order for me to maintain understanding of what was going on, I needed to clean it up a little.</li>
</ol>
<h2>Let&#8217;s Code&#8230;</h2>
<p>Well, for starters, to accomplish #1, I had to write a function that would validate the user&#8217;s app key with Ping.fm:<br />
{code type=php}<br />
/* [[Neo]] */<br />
//BEGIN Ping.fm functions<br />
function pingfm_verify() {<br />
	// request app key verification<br />
	$ch = curl_init();<br />
	curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);<br />
	curl_setopt($ch, CURLOPT_POST, true);<br />
	curl_setopt($ch, CURLOPT_URL, &#8216;http://api.ping.fm/v1/user.validate&#8217;);<br />
	curl_setopt($ch, CURLOPT_POSTFIELDS, Array(<br />
		&#8216;api_key&#8217; =&gt; get_option(&#8216;tweetsuite_ping_api_key&#8217;),<br />
		&#8216;user_app_key&#8217; =&gt; get_option(&#8216;tweetsuite_ping_app_key&#8217;)<br />
	));<br />
	$output = curl_exec($ch);<br />
	// update database with response<br />
	if (preg_match(&#8216;/OK/&#8217;, $output)) {<br />
		echo &#8216;	&lt;strong&gt;Your key has been verified.&lt;/strong&gt; Your can now post to your<br />
				&lt;a href=&#8221;http://www.ping.fm&#8221; target=&#8221;_blank&#8221;&gt;Ping.fm&lt;/a&gt; account.&#8217;;<br />
		update_option(&#8216;tweetsuite_ping_keyVerified&#8217;, 1);<br />
	} else {<br />
		echo (&#8216;&lt;strong&gt;Your key could not be verified.&lt;/strong&gt;.&#8217;);<br />
		update_option(&#8216;tweetsuite_ping_keyVerified&#8217;, 0);<br />
		return false;<br />
	}<br />
}</p>
<p>// END Ping.fm Functions<br />
{/code}<br />
Just your basic <span style="font-family: 'Courier New'; line-height: 18px; white-space: pre;">curl</span><span style="font-family: Georgia; line-height: 19px; white-space: normal;"> function to contact </span><span style="font-family: 'Courier New'; line-height: 18px; white-space: pre;">http://api.ping.fm/v1/user.validate</span><span style="font-family: Georgia; line-height: 19px; white-space: normal;"> and pass the api_key and user_app_key to the api, per the <a href="http://groups.google.com/group/pingfm-developers/web/api-documentation?pli=1#user.validate" target="_blank">API Documentation</a> on <strong>user.validate</strong>. Depending on the response, store it to the database, and display the appropriate message.</span></p>
<p><span style="font-family: Georgia; line-height: 19px; white-space: normal;">Next, I had to implement the fields to make that happen. We&#8217;ll start with the database&#8230;</span><br />
{code type=php}<br />
/* [[Neo]] */<br />
//ADDED:<br />
	add_option(&#8216;tweetsuite_ping_api_key&#8217;,&#8217;333333333333333333333333333333333&#8242;);<br />
	add_option(&#8216;tweetsuite_ping_app_key&#8217;,&#8221;);<br />
	add_option(&#8216;tweetsuite_use_ping&#8217;,0);<br />
	add_option(&#8216;tweetsuite_ping_keyVerified&#8217;,0);<br />
//END ADD<br />
{/code}<br />
This sticks those fields into the wordpress database table &#8220;wp_options&#8221; where all the config values go. My developer&#8217;s api key, a blank user application key, a field for the checkbox &#8220;Do you want to use Ping.fm?&#8221; and one for whether or not the user_app_key successfully verified.</p>
<p>Then I create the user interface for those fields (as well as rearrange the rest of the fields since these have to flow right to make sense&#8230;<br />
{code type=php}<br />
/* [[Neo]] */<br />
//ADDED:<br />
	update_option(&#8216;tweetsuite_ping_app_key&#8217;, $_POST['tweetsuite_ping_app_key']);<br />
//END ADD</p>
<p>//tweetsuite_use_ping<br />
($_POST['tweetsuite_use_ping']) ? update_option(&#8216;tweetsuite_use_ping&#8217;, 1) : update_option(&#8216;tweetsuite_use_ping&#8217;, 0);<br />
{/code}</p>
<p>That part allows the database to be updated with the data from the fields below&#8230;<br />
{code type=html}<br />
&lt;!&#8211; /* [[Neo]] */ &#8211;&gt;<br />
&lt;!&#8211; BEGIN ADD &#8211;&gt;<br />
&lt;tr valign=&#8221;top&#8221;&gt;<br />
	&lt;th scope=&#8221;row&#8221;&gt;Ping.fm :: Use Ping.fm to publish new posts (via your default method)?:&lt;/th&gt;<br />
	&lt;td&gt;&lt;INPUT TYPE=CHECKBOX NAME=&#8221;tweetsuite_use_ping&#8221; &lt;?php if(get_option(&#8216;tweetsuite_use_ping&#8217;)) { echo &#8220;checked&#8221;; } ?&gt;&gt;<br />
		&lt;br /&gt;&lt;b&gt;["Send a Tweet when you publish" is required for this to work]&lt;/b&gt;<br />
	&lt;/td&gt;<br />
&lt;/tr&gt;<br />
&lt;tr valign=&#8221;top&#8221;&gt;<br />
	&lt;th scope=&#8221;row&#8221;&gt;Ping.fm :: Your Ping.fm &lt;a href=&#8221;http://ping.fm/key/&#8221; target=&#8221;_blank&#8221;&gt;Application Key&lt;/a&gt;:&lt;/th&gt;<br />
	&lt;td&gt;&lt;INPUT TYPE=text NAME=&#8221;tweetsuite_ping_app_key&#8221;  value=&#8217;&lt;?php echo get_option(&#8216;tweetsuite_ping_app_key&#8217;); ?&gt;&#8217; /&gt;&lt;br /&gt;&lt;?php if(get_option(&#8216;tweetsuite_ping_app_key&#8217;)) { echo pingfm_verify(); } ?&gt;<br />
	&lt;/td&gt;<br />
&lt;/tr&gt;<br />
&lt;!&#8211; END ADD &#8211;&gt;<br />
{/code}<br />
This is below the checkbox for &#8220;Send a Tweet when you publish a post?&#8221;&#8230;if that is checked, then if you check &#8220;Use Ping.fm to publish new posts (via your default method)?&#8221; and fill out the next field for &#8220;Your Ping.fm <a href="http://ping.fm/key/" target="_blank">Application Key</a>&#8221; then it will send your post details on Publish through Ping.fm instead of Twitter itself, appending the tinyurl associated with the post to your Ping.fm message. All this is done by editing the function that sends the tweets&#8230;<br />
{code type=php}<br />
function tweetsuite_send($msg) {<br />
	/* [[Neo]] */<br />
	//REMOVED:<br />
	//$prefix = urlencode(get_option(&#8216;tweetsuite_prefix&#8217;).&#8217; &#8216;);<br />
	//REPLACED:<br />
	$prefix = (get_option(tweetsuite_use_ping) and get_option(tweetsuite_ping_keyVerified)) ? get_option(&#8216;tweetsuite_prefix&#8217;).&#8217; &#8216; : urlencode(get_option(&#8216;tweetsuite_prefix&#8217;).&#8217; &#8216;);<br />
	$msg = $prefix.$msg;</p>
<p>	/* [[Neo]] */<br />
	//ADDED<br />
	if(get_option(tweetsuite_use_ping) and get_option(tweetsuite_ping_keyVerified)) {<br />
		$ch = curl_init();<br />
		curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);<br />
		curl_setopt($ch, CURLOPT_POST, true);<br />
		curl_setopt($ch, CURLOPT_URL, &#8216;http://api.ping.fm/v1/user.post&#8217;);<br />
		curl_setopt($ch, CURLOPT_POSTFIELDS, Array(<br />
			&#8216;api_key&#8217; =&gt; get_option(&#8216;tweetsuite_ping_api_key&#8217;),<br />
			&#8216;user_app_key&#8217; =&gt; get_option(&#8216;tweetsuite_ping_app_key&#8217;),<br />
			&#8216;post_method&#8217; =&gt; &#8220;default&#8221;,<br />
			&#8216;body&#8217; =&gt; $msg)<br />
		);<br />
		$output = curl_exec($ch);<br />
	} else {<br />
		//END ADD<br />
		$username = get_option(&#8216;tweetsuite_twitter_username&#8217;);<br />
		$password = get_option(&#8216;tweetsuite_twitter_password&#8217;);<br />
		if(($username) and ($password))  {<br />
			$url = &#8216;http://twitter.com/statuses/update.xml&#8217;;<br />
			$curl_handle = curl_init();<br />
			curl_setopt($curl_handle, CURLOPT_URL, &#8220;$url&#8221;);<br />
			curl_setopt($curl_handle, CURLOPT_CONNECTTIMEOUT, 2);<br />
			curl_setopt($curl_handle, CURLOPT_RETURNTRANSFER, 1);<br />
			curl_setopt($curl_handle, CURLOPT_POST, 1);<br />
			curl_setopt($curl_handle, CURLOPT_POSTFIELDS, &#8220;status=$msg&#8221;);<br />
			curl_setopt($curl_handle, CURLOPT_USERPWD, &#8220;$username:$password&#8221;);<br />
			$buffer = curl_exec($curl_handle);<br />
			curl_close($curl_handle);<br />
		}<br />
	/* [[Neo]] */<br />
	//ADDED<br />
	}<br />
	//END ADD<br />
}<br />
{/code}<br />
This starts off by swapping out the original <strong>urlencode()</strong> function for a conditional statement deciding if this is a ping.fm post or a twitter post. If it&#8217;s a ping.fm post, then we don&#8217;t want to <strong>urlencode()</strong> the prefix, because it sticks + signs where there should be spaces in the prefix to the title. However, if we don&#8217;t want to use ping.fm, then don&#8217;t mess with the original code.</p>
<p>Following that, it splits which method we used to post, based on the same criteria &#8211; make sure the checkbox is true for &#8220;tweetsuite_use_ping&#8221; and that the user&#8217;s app key is verified in &#8220;tweetsuite_ping_keyVerified&#8221;. If that&#8217;s the case, then post it through ping.fm &#8211; if any of that is not met, then go ahead and try to post it through twitter. If there is no username and password supplied on the options page, then we just won&#8217;t post anything.</p>
<p>Now&#8230;about the whole $msg &#8211; that part got skipped in the logic of everything. This was the tricky part, for me. Originally, I stumbled across an API Documentation page for the ping.fm method &#8220;url.shorten&#8221; and that was the very thing I needed &#8211; something to grab a ping.fm url, without passing it through ping.fm yet. However, I found out, after much frustration, that this method was mysteriously &#8220;depreciated&#8221; (which should be read as &#8220;edited off the page, and 404&#8242;d when you try to use it). But, I found <a href="http://groups.google.com/group/pingfm-developers/browse_thread/thread/e6bf14bd63fdb7df/e59e3c16424ad20f?lnk=gst&amp;q=url+shortening#e59e3c16424ad20f" target="_blank">another solution</a> in the knowledgebase at Ping.fm&#8230;<br />
{code type=php}<br />
function ts_send_tweet($postID) {<br />
	global $wpdb;<br />
	if(!is_int($postID))<br />
		$postID = $postID-&gt;ID;</p>
<p>	$table_name = $wpdb-&gt;prefix . &#8220;shorturls&#8221;;<br />
	$line = $wpdb-&gt;get_row(&#8220;select * from $table_name where postID=$postID&#8221;);<br />
	if($line-&gt;postID==$postID) {<br />
		/* [[Neo]] */<br />
		// ADDED: &#8220;*&#8221;.<br />
		$shorturl = &#8220;*&#8221;.$line-&gt;tinyurl;<br />
		$post = get_post($postID);<br />
		if(get_option(&#8216;tweetsuite_send_posts&#8217;))<br />
			tweetsuite_send(trim($post-&gt;post_title).&#8217; &#8216;.$shorturl);<br />
	}<br />
}<br />
{/code}<br />
The article said you can prepend a <strong>* </strong>to the front of a url and it would not shorten it (in addition to the fact that they said they wouldn&#8217;t re-shorten any URLs 24 characters or smaller). So, I went with the * solution, because we&#8217;re already providing short URLs, but don&#8217;t want to risk the functionality in future updates to allow for custom url shortening services.</p>
<p>And that accomplishes both #1 and #2. We have the TweetSuite posting its updates through the Ping.fm API, and pushing a shortened url out with the post. TweetSuite then becomes aware of this url at publish, and stores it in its database. Then the cron job that runs every 5 minutes searches on any version of the URL that was stored and pulls back all the entries from the search.twitter.com Atom feed &#8211; parses them, and updates the database with them.</p>
<p>The rest of the stuff I did in the plugin was merely cleaning up&#8230;for example, reading the shortened urls from the Atom feed. The original code was:<br />
{code type=php}<br />
if(stristr($tweet, &#8216;http://bit.ly&#8217;)) {<br />
	if(strstr($tweet, $bitly)) {<br />
		$add = true;<br />
	} else {<br />
		$add = false;<br />
	}<br />
}<br />
{/code}<br />
Because the urls are using alphanumeric sequences to track what link is what &#8211; and the url&#8217;s are case-sensitive, it was returning links that were not related to the post. For example, I got <a href="http://twitter.com/lukebuchanan/statuses/1332713478" target="_blank">someone&#8217;s tweet about Rush Limbaugh</a> because the bit.ly url (&#8220;http://bit.ly/fyhz&#8221;)was the same letters, but in a different case then my original &#8220;http://bit.ly/FyhZ&#8221;. So I changed the order of the search, did it for all the services currently supported, and cleaned up the code a little:<br />
{code type=php}&#8230;<br />
if(strstr($tweet, &#8216;http://bit.ly&#8217;)) { $add = (stristr($tweet, $bitly)) ? true : false; } else {<br />
&#8230;<br />
{/code}<br />
The function<strong> strstr() </strong>is <strong>not</strong> case-sensitive, and that&#8217;s ok for a search on the domain name &#8211; we want anything that looks close to &#8220;bit.ly&#8221; to return positive. However, once it does, it&#8217;s imperitive that we use the case-sensitive <strong>stristr()</strong> function to return a positive result only if the full url matches what we have in the database case-for-case.</p>
<h2>Wrapping up&#8230;</h2>
<p>I made a couple more additions to the code beyond that, some of them required for functionality, some of them for cosmetics. I&#8217;ve submitted my plugin version to Ping.fm to approve it, and take my Developer&#8217;s Key out of &#8220;Pending&#8221; status. Once that&#8217;s done, I&#8217;ll send it off to Dan Zarrella to take a look and see how he wants to move forward. Then I&#8217;ll be able to post the plugin for download (definitely here, but also on the WordPress Plugin directory.</p>
<h2>Continuing on&#8230;</h2>
<p>I have read through the comments on Dan&#8217;s blog from the people, and have taken note of the things that they are asking for. After reading the code, he had already been working on some of the features. There are 5 main ones that people are asking for, and I&#8217;ve already done one of them in this release:</p>
<ol>
<li><span style="text-decoration: line-through;">TweetThis link opens in a new window.</span></li>
<li>AutoUpgrade via WordPress Plugin Directory</li>
<li>Allow customized URL Shortening Services</li>
<li>TweetThis links for pre-installation posts</li>
<li>TweetThis links on the home page.</li>
</ol>
<p>I&#8217;ll be looking more into the other options and see what I can do.</p>
<h2>One More Thing&#8230;</h2>
<p>This post was syndicated through the TweetSuite + Ping.fm plugin <img src='http://thepizzy.net/blog/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' />  .</p>

<!-- start wp-tags-to-technorati 1.02 -->

<p class='technorati-tags'>Technorati Tags: <a class='technorati-link' href='http://technorati.com/tag/beta' rel='tag' target='_blank'>beta</a>, <a class='technorati-link' href='http://technorati.com/tag/dan+zarrella' rel='tag' target='_blank'>dan zarrella</a>, <a class='technorati-link' href='http://technorati.com/tag/database' rel='tag' target='_blank'>database</a>, <a class='technorati-link' href='http://technorati.com/tag/internet' rel='tag' target='_blank'>internet</a>, <a class='technorati-link' href='http://technorati.com/tag/MySQL' rel='tag' target='_blank'>MySQL</a>, <a class='technorati-link' href='http://technorati.com/tag/PHP' rel='tag' target='_blank'>PHP</a>, <a class='technorati-link' href='http://technorati.com/tag/Ping.fm' rel='tag' target='_blank'>Ping.fm</a>, <a class='technorati-link' href='http://technorati.com/tag/site' rel='tag' target='_blank'>site</a>, <a class='technorati-link' href='http://technorati.com/tag/syndication' rel='tag' target='_blank'>syndication</a>, <a class='technorati-link' href='http://technorati.com/tag/tweetbacks' rel='tag' target='_blank'>tweetbacks</a>, <a class='technorati-link' href='http://technorati.com/tag/TweetSuite' rel='tag' target='_blank'>TweetSuite</a>, <a class='technorati-link' href='http://technorati.com/tag/twitter' rel='tag' target='_blank'>twitter</a>, <a class='technorati-link' href='http://technorati.com/tag/Wordpress' rel='tag' target='_blank'>WordPress</a></p>

<!-- end wp-tags-to-technorati -->
]]></content:encoded>
			<wfw:commentRss>http://thepizzy.net/blog/2009/03/tweetsuite-wordpress-plugin-pingfm-preview/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
	</channel>
</rss>

