<?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>Brian Bell &#187; WebDev</title>
	<atom:link href="http://webguru.org/category/webdev/feed/" rel="self" type="application/rss+xml" />
	<link>http://webguru.org</link>
	<description>Bits of web-dev, travel and personal musings...</description>
	<lastBuildDate>Mon, 09 Nov 2009 21:36:16 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.8.5</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>How to use Google Charts API in your Secure, HTTPS webpage</title>
		<link>http://webguru.org/2009/11/09/php/how-to-use-google-charts-api-in-your-secure-https-webpage/</link>
		<comments>http://webguru.org/2009/11/09/php/how-to-use-google-charts-api-in-your-secure-https-webpage/#comments</comments>
		<pubDate>Mon, 09 Nov 2009 21:36:16 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[LAMP]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[WebDev]]></category>
		<category><![CDATA[api]]></category>
		<category><![CDATA[google charts]]></category>
		<category><![CDATA[https]]></category>

		<guid isPermaLink="false">http://webguru.org/?p=42</guid>
		<description><![CDATA[So you love Google Charts API and want to spice up your app with lots of pretty bar charts, Venn diagrams, Google-o-meters and 2D bar codes (QR Codes) &#8211; only problem is, you require that users connect to your site using a secure connection (https://yoursite.com/whatever).  Well, as you are probably aware, the Google Charts [...]]]></description>
			<content:encoded><![CDATA[<p>So you love Google Charts API and want to spice up your app with lots of pretty bar charts, Venn diagrams, Google-o-meters and 2D bar codes (QR Codes) &#8211; only problem is, you require that users connect to your site using a secure connection (<strong>https</strong>://yoursite.com/whatever).  Well, as you are probably aware, the Google Charts API doesn&#8217;t ex</p>
<p>actly support SSL connections&#8230; directly.</p>
<p>Have no fear! If you are willing to give up a little bit of your own bandwidth, you can work around this problem.  We are going to do this using a simple PHP script and if you want to get really fancy, Memcached to keep the redundant API calls to a minimum.</p>
<p>Let&#8217;s get started.<br />
<span id="more-42"></span><br />
First, let&#8217;s make sure we understand why it is a problem to include a non-secure Google Charts API into your otherwise secure page.  When your users are browsing to your page using an address starting with <strong>https://</strong>, their browser is going to negotiate an TLS/SSL connection which will encrypt all the data flowing between your client and the server.  If any element on the page (image, external CSS or JavaScript, etc.) is not being called from a secured connection as well, then the browser will throw up a warning.  Each browser is different, but most will alert the user with a broken lock and/or a popup message.  The user can usually accept this warning and proceed at their own risk, but this is not acceptable for a production website or application.</p>
<p>The obvious answer to this problem is to make sure that all external elements on the page are loaded over a secure connection.  So &#8211; how do we do that with Google Charts? Google does not allow you to just take a traditional API call and slap a &#8220;https://&#8221; in front of it in lieu of the expected http://.  Your request will be <strong>denied</strong>.</p>
<h2>Basic Implementation</h2>
<p>Here&#8217;s what we do:</p>
<ol>
<li>Create a simple PHP script that will fetch a chart from Google Charts API</li>
<li>Change your web page to call the new PHP &#8220;fetcher&#8221; instead of Google Charts directly.</li>
<li>Make sure the PHP script is being called by your page over your https:// connection</li>
</ol>
<p>It is pretty much that simple.</p>
<p>Here is the before example:</p>
<pre class="brush: xml;">
&lt;!-- HTML snippet --&gt;
&lt;img src='http://chart.apis.google.com/chart?cht=p&amp;chd=s:Uf9a&amp;chs=200x100&amp;chl=January|February|March|April' alt='Pie Chart'/&gt;
</pre>
<p>Here is the after example:</p>
<pre class="brush: xml;">
&lt;!-- HTML snippet --&gt;
&lt;img src='https://mywebsite.com/gchart.php?api_url=http%3A%2F%2Fchart.apis.google.com%2Fchart%3Fcht%3Dp%26chd%3Ds%3AUf9a%26chs%3D200x100%26chl%3DJanuary%7CFebruary%7CMarch%7CApril' alt='Pie Chart'/&gt;
</pre>
<p>Notice, the same API URI is used in the &#8220;after&#8221; example, <strong>but it is URL Encoded</strong>.  This just makes it safer to pass along to the PHP script.</p>
<p>Here is the PHP script that makes this work:</p>
<pre class="brush: php;">
&lt;?php

$url = urldecode($_GET['api_url']);

$image_contents = file_get_contents($url);
echo $image_contents;
exit;
</pre>
<p>A quick note about this: you may be saying &#8211; where is your closing PHP tag!?!  Well, PHP doesn&#8217;t require that you have a closing PHP tag, as the PHP interpreter will automatically close any open tags.  I do this on just about every file that will be used as an include of some sorts &#8211; particularly in something like this where any extra, inadvertent white space at the end of the file can alter the output adversely and cause errors in the page.</p>
<h2>Advanced Implementation w/ Caching</h2>
<p>The script as it is above, is fine and dandy, but terribly inefficient.  You see, every time the user requests the page, your script is going out and using <strong>your bandwidth</strong> to make the request to the Google Charts API instead of the client.  You are becoming the proxy for all requests to and from Google Charts.  This will not fly &#8211; especially if you are in a high volume environment.</p>
<p>So what is the solution? I chose Memcache to store a copy of the image contents for a certain period of time before having to re-query the Charts API and re-fetch the data again.</p>
<p>It looks something like this:</p>
<pre class="brush: php;">
&lt;?php

$url = urldecode($_GET['api_url']);
$cache_key = md5($url);
$item_cache_expire = 3600;
$mc_host = '127.0.0.1';
$mc_port = 11211;

# Connect to Memcache
$memcache = new Memcache;
$memcache-&gt;connect($mc_host, $mc_port) or die (&quot;Could not connect&quot;);

if ( $get_result = $memcache-&gt;get($cache_key) ) {
    $image_contents = $get_result-&gt;chart_image;
}
else {
    $image_contents = file_get_contents($url);

    $tmp_object = new stdClass;
    $tmp_object-&gt;chart_image = $image_contents;

    $memcache-&gt;set($cache_key, $tmp_object, false, $item_cache_expire) or die (&quot;Failed to save data at the server&quot;);

}
echo $image_contents;
exit;
</pre>
<p>Here&#8217;s what is happening. </p>
<pre class="brush: php;">
&lt;?php

$url = urldecode($_GET['api_url']);
$cache_key = md5($url);
$item_cache_expire = 3600;
$mc_host = '127.0.0.1';
$mc_port = 11211;
</pre>
<p>Setup some variables we&#8217;ll need in the script.  Grab the api_url value from the GET array, create an MD5 hash of the request URL (we&#8217;ll use this as our memcache item key), set the expiration time of the cached item to 3600 seconds (a.k.a. 1 hour) and finally provide the connection information to your memecached server. </p>
<pre class="brush: php;">
# Connect to Memcache
$memcache = new Memcache;
$memcache-&gt;connect($mc_host, $mc_port) or die (&quot;Could not connect&quot;);
</pre>
<p>Instantiate a new Memcache object using the connection info provided above.</p>
<pre class="brush: php;">
if ( $get_result = $memcache-&gt;get($cache_key) ) {
    $image_contents = $get_result-&gt;chart_image;
}
else {
    $image_contents = file_get_contents($url);

    $tmp_object = new stdClass;
    $tmp_object-&gt;chart_image = $image_contents;

    $memcache-&gt;set($cache_key, $tmp_object, false, $item_cache_expire) or die (&quot;Failed to save data at the server&quot;);
}
</pre>
<p>Using the MD5 hash that we created above, check to see if there is a valid cached object on the memcache server for us to retrieve.  If not, go out and grab a fresh version from Google Charts API and stick it into memcache.  Either way, we end up with a variable $image_contents which contains the desired chart image.</p>
<pre class="brush: php;">
echo $image_contents;
exit;
</pre>
<p>All that is left to do now is print out the image contents and exit the script.  Again, I do not use a closing PHP tag on purpose to avoid extra whitespace.</p>
<h2>All ye, all ye, now hear this&#8230;</h2>
<p>This is a very basic example.  It should probably be categorized more as a proof of concept. It does NOT, I repeat &#8211; DOES NOT &#8211; take into account a variety of security concerns such as SQL injection or CSRF (cross-site request forgeries), etc. Notice that I didn&#8217;t even validate the user input from the GET variable.  Who does that!?!  So, in other words, don&#8217;t just copy and paste and then come back and blame me for getting your site hacked.  Be smart about employing something like this.</p>
<p>BTW, if you want to know more about how to make your PHP scripts more secure, go see Chris Shifflet&#8217;s excellent blog at <a href="http://shiflett.org/" target="_blank">http://shiflett.org/</a>.  </p>
]]></content:encoded>
			<wfw:commentRss>http://webguru.org/2009/11/09/php/how-to-use-google-charts-api-in-your-secure-https-webpage/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Memory-tight, multi-threaded PHP Daemon</title>
		<link>http://webguru.org/2008/11/17/php/memory-tight-multi-threaded-php-daemon/</link>
		<comments>http://webguru.org/2008/11/17/php/memory-tight-multi-threaded-php-daemon/#comments</comments>
		<pubDate>Mon, 17 Nov 2008 15:49:02 +0000</pubDate>
		<dc:creator>Brian</dc:creator>
				<category><![CDATA[LAMP]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[WebDev]]></category>

		<guid isPermaLink="false">http://webguru.org/2008/11/17/php/memory-tight-multi-threaded-php-daemon/</guid>
		<description><![CDATA[Came across this nifty project on Google Code.  It&#8217;s a multi-threaded, object-oriented PHP daemon which is very nicely written and easy to use.
http://code.google.com/p/phpmultithreadeddaemon/
Here&#8217;s their example of how to implement it.  Everything needed to run the daemon is in the single included file &#8220;class.MTDaemon.php&#8221; &#8211; cool!


&#60;?php

error_reporting(E_ALL);

require_once(include/class.MTDaemon.php);

class MTTest extends MTDaemon {

public function getNext($slot)
{
$this-&#62;lock();
$num = $this-&#62;getVar(&#34;num&#34;);
if [...]]]></description>
			<content:encoded><![CDATA[<p>Came across this nifty project on Google Code.  It&#8217;s a multi-threaded, object-oriented PHP daemon which is very nicely written and easy to use.</p>
<p><a href="http://code.google.com/p/phpmultithreadeddaemon/" title="PHP Daemon Project on Google Code">http://code.google.com/p/phpmultithreadeddaemon/</a></p>
<p>Here&#8217;s their example of how to implement it.  Everything needed to run the daemon is in the single included file &#8220;class.MTDaemon.php&#8221; &#8211; cool!</p>
<pre class="brush: php;">

&lt;?php

error_reporting(E_ALL);

require_once(include/class.MTDaemon.php);

class MTTest extends MTDaemon {

public function getNext($slot)
{
$this-&gt;lock();
$num = $this-&gt;getVar(&quot;num&quot;);
if ($num == null) $num = 1;
if ($num &gt; 100) {
$this-&gt;unlock();
return null;
}
$this-&gt;unlock();

$rand = rand(0, 5);
echo &quot;Next for slot &quot; . $slot . &quot; : &quot; . $rand . &quot;\n&quot;;
if ($rand == 0) return null;
else return $rand;
}

public function run($next, $slot)
{
$rand = rand(3, 10);
$this-&gt;lock();
$num = $this-&gt;getVar(&quot;num&quot;);
$this-&gt;setVar(&quot;num&quot;, $this-&gt;getVar(&quot;num&quot;) + 1);
$this-&gt;unlock();
echo &quot;## Iteration #&quot; . number_format($num) . &quot; in &quot; . $rand . &quot;sec&quot; . &quot;\n&quot;;

sleep($rand);
return 0;
}

}

$mttest = new MTTest(2);
$mttest-&gt;handle();

?&gt;
</pre>
]]></content:encoded>
			<wfw:commentRss>http://webguru.org/2008/11/17/php/memory-tight-multi-threaded-php-daemon/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>MySQL ON DUPLICATE KEY INSERT</title>
		<link>http://webguru.org/2007/12/18/lamp/mysql-on-duplicate-key-insert/</link>
		<comments>http://webguru.org/2007/12/18/lamp/mysql-on-duplicate-key-insert/#comments</comments>
		<pubDate>Tue, 18 Dec 2007 14:54:30 +0000</pubDate>
		<dc:creator>Brian</dc:creator>
				<category><![CDATA[LAMP]]></category>
		<category><![CDATA[WebDev]]></category>
		<category><![CDATA[mysql]]></category>

		<guid isPermaLink="false">http://webguru.org/2007/12/18/lamp/mysql-on-duplicate-key-insert/</guid>
		<description><![CDATA[Have you ever wanted to write a single query that would update fields in a table &#8211; but you can&#8217;t be 100% sure the record exists yet for you to update?  For example, you might have a table that holds configuration data for your application.  There will be one record for each user [...]]]></description>
			<content:encoded><![CDATA[<p>Have you ever wanted to write a single query that would update fields in a table &#8211; but you can&#8217;t be 100% sure the record exists yet for you to update?  For example, you might have a table that holds configuration data for your application.  There will be one record for each user in your system.  You could use their &#8220;UserID&#8221; as the primary key (that is crucial to making this work).</p>
<p>Well, instead of doing this:</p>
<pre class="brush: php;">
&lt;?php
$sql = &quot;SELECT COUNT(UserID) FROM configuration WHERE UserID='SomeUser'&quot;;
$result = mysqli_query($db,$sql);
if ($result &amp;&amp; mysqli_num_rows($result)&gt;0) {
$aResult = mysqli_fetch_array($result);
$iRecordExists = ($aResult[0]&gt;0?1:0);
}

if ($iRecordExists&gt;0) {
//do an update
$sql = &quot;UPDATE configuration SET someField='someValue' WHERE UserID='SomeUser'&quot;;
mysqli_query($db,$sql);
}
else {
//do an insert
$sql = &quot;INSERT INTO configuration SET someField='someValue', UserID='SomeUser'&quot;;
mysqli_query($db,$sql);
}
?&gt;
</pre>
<p>You could just do this:</p>
<pre class="brush: php;">

&lt;?php
//insert the user's configuration field - if the record already exists - update instead
$sql = &quot;INSERT INTO configuration SET UserID='SomeUser', someField='someValue' ON DUPLICATE KEY UPDATE someField='someValue' &quot;;
mysqli_query($db,$sql);
?&gt;
</pre>
<p>Simply put, the query will attempt to insert the configuration record first.  If it finds that the specified UserID already has a configuration record in the table, it will simply update the existing record according to the values you include after &#8220;ON DUPLICATE KEY UPDATE&#8221;.  You can include more than one field to update as well.<br />
<br />
[Update: As Paul questioned in the comment below, the WHERE clause is not correct (in my original post).  The trick is, you have to include the primary key as part of the insert statement - such as UserID in the example above.]</p>
]]></content:encoded>
			<wfw:commentRss>http://webguru.org/2007/12/18/lamp/mysql-on-duplicate-key-insert/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Why I switched to a new IDE for PHP development</title>
		<link>http://webguru.org/2007/11/27/php/why-i-switched-to-a-new-ide-for-php-development/</link>
		<comments>http://webguru.org/2007/11/27/php/why-i-switched-to-a-new-ide-for-php-development/#comments</comments>
		<pubDate>Tue, 27 Nov 2007 16:09:09 +0000</pubDate>
		<dc:creator>Brian</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[WebDev]]></category>
		<category><![CDATA[dreamweaver]]></category>
		<category><![CDATA[editor]]></category>
		<category><![CDATA[ide]]></category>
		<category><![CDATA[nusphere]]></category>

		<guid isPermaLink="false">http://webguru.org/2007/11/27/php/why-i-switched-to-a-new-ide-for-php-development/</guid>
		<description><![CDATA[I've been using Dreamweaver for about 10 years in some form or fashion.  It actually started when I purchased Allaire HomeSite 3.0 in 1997.  Macromedia purchased Allaire in 2001 and eventually merged HomeSite with their Dreamweaver product.  Dreamweaver 8 is what I've been using for the past 2 years; that is, until I found PHP nirvana!

I have tried other IDE's off and on for the past 5 years - trying to get more of a Visual Studio experience.  I was really jealous of the code-completion and hinting features that were available in VS.  Dreamweaver does ok at basic function hints for PHP, but nothing I found did a great job of combining all the site management features of Dreamweaver with the intelligent code parsing (ie. reading my classes and adding them to the code-completion hints).   I've tried Eclipse with its PHP plug-in, UltraEdit, Zend Studio, phpDesigner and probably some others that I'm not listing.]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve been using Dreamweaver for about 10 years in some form or fashion.  It actually started when I purchased Allaire HomeSite 3.0 in 1997.  Macromedia purchased Allaire in 2001 and eventually merged HomeSite with their Dreamweaver product.  Dreamweaver 8 is what I&#8217;ve been using for the past 2 years; that is, until I found PHP nirvana!</p>
<p>I have tried other IDE&#8217;s off and on for the past 5 years &#8211; trying to get more of a Visual Studio experience.  I was really jealous of the code-completion and hinting features that were available in VS.  Dreamweaver does ok at basic function hints for PHP, but nothing I found did a great job of combining all the site management features of Dreamweaver with the intelligent code parsing (ie. reading my classes and adding them to the code-completion hints).   I&#8217;ve tried Eclipse with its PHP plug-in, UltraEdit, Zend Studio, phpDesigner and probably some others that I&#8217;m not listing.</p>
<div align='center'><img src="http://webguru.org/content/phped-workspace-thumb.png" alt="PhpED Workspace" width="550" /></div>
<p><span id="more-14"></span><br />
I can&#8217;t remember exactly when I first downloaded NuSphere PhpED for the first time; but recently I thought I&#8217;d give it yet another shot.  Man, was I surprised! I&#8217;m using version 5.2 and it is awesome.  It is the first time that I have what I consider to be a truly fully integrated development environment.  It has projects (who doesn&#8217;t), an SSH client, SFTP/FTP, intelligent code completion based on my classes, an excellent code navigator which details class methods &amp; variables, an integrated debugger with its own WAMP stack, server-side debugging (optional) and more!  </p>
<p>I can already tell after using it for a week that its going to save me a ton of time and help me write better code.  </p>
<p>Here are my top 5 features that I really love (in no particular order)&#8230;</p>
<ol>
<li><strong>Code Snippets:</strong> just type something like &#8220;func&#8221; and hit Ctrl+J to insert a full function block.  You can add whatever snippets you want and even choose where to place the cursor when it is inserted (crucial time saver and major annoyance avoider).</li>
<li><strong>Code/Variable completion:</strong> when you start typing a object it will provide you with all the available class methods along with their parameters.  It will auto-complete variable names with respect to the document scope, based on your cursor position.  In other words, if you&#8217;re working inside function it will know to only show you variables that were declared in that function or class-wide vars.</li>
<li><strong>Internal Debugger:</strong> you can step through your code and instantly see where there are problems without having to do the save, upload, open browser, check for error dance.</li>
<li><strong>Extremely customizable:</strong> I was quickly able to modify the keyboard shortcuts to what I was used to using in Dreamweaver.</li>
<li><strong>Integrated SSH client:</strong> I love PuTTY just as much as the next person, but how cool is it that you can have a shell open in a tab right next to the document you&#8217;re working on.</li>
</ol>
<p>The only downside is that NuSphere PhpED is not F/OSS.  I paid $199 for the professional version; but really &#8211; that isn&#8217;t bad compared to Dreamweaver &#8211; and it&#8217;s proving to be an awesome tool for my purposes.</p>
<p>What are you using?</p>
]]></content:encoded>
			<wfw:commentRss>http://webguru.org/2007/11/27/php/why-i-switched-to-a-new-ide-for-php-development/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>On-the-fly Form Validation with JavaScript Regular Expressions</title>
		<link>http://webguru.org/2007/11/19/webdev/on-the-fly-form-validation-with-javascript-regular-expressions/</link>
		<comments>http://webguru.org/2007/11/19/webdev/on-the-fly-form-validation-with-javascript-regular-expressions/#comments</comments>
		<pubDate>Mon, 19 Nov 2007 20:17:51 +0000</pubDate>
		<dc:creator>Brian</dc:creator>
				<category><![CDATA[WebDev]]></category>

		<guid isPermaLink="false">http://webguru.org/2007/11/19/general/on-the-fly-form-validation-with-javascript-regular-expressions/</guid>
		<description><![CDATA[I needed to check a text input field on a form to allow only specific values as the user typed in the field.  The regular expression only allows characters a-z, numbers 0-9, the &#8220;dash&#8221; symbol and the underscore. Not sure why, but I had to break out the check for a space into a [...]]]></description>
			<content:encoded><![CDATA[<p>I needed to check a text input field on a form to allow only specific values as the user typed in the field.  The regular expression only allows characters a-z, numbers 0-9, the &#8220;dash&#8221; symbol and the underscore. Not sure why, but I had to break out the check for a space into a second regex.</p>
<pre>
Here's the JavaScript function:
<pre class="brush: jscript;">
&lt;script language=&quot;javascript&quot; type=&quot;text/javascript&quot;&gt;
function testField(oField) {

	var illegalChars = /[^a-zA-Z0-9_-]/;
	var spaceChars = /\s/;
		// allow only letters, numbers, dashes and underscores
	if (illegalChars.test(oPrefix.value) || spaceChars.test(oPrefix.value)) {
		alert(&quot;The prefix may only contain letters, numbers, dashes and underscores.&quot;);
		oPrefix.value = oPrefix.value.substring(0,oPrefix.value.length-1).toUpperCase();
	}
	else {
		oPrefix.value = oPrefix.value.toUpperCase();
	}

}
&lt;/script&gt;
</pre>
<p>And here's the HTML form that calls the script through the "onKeyUp" action.</p>
<pre class="brush: xml;">
&lt;form name='frmTest' method=&quot;POST&quot; action=&quot;somepage.php&quot;&gt;
Text: &lt;input type='text' name='someFieldName' value='' maxlength=&quot;5&quot; style=&quot;width:65px;&quot;  onkeyup=&quot;testField(this)&quot;&gt;
&lt;/form&gt;
</pre>
</pre>
]]></content:encoded>
			<wfw:commentRss>http://webguru.org/2007/11/19/webdev/on-the-fly-form-validation-with-javascript-regular-expressions/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
	</channel>
</rss>

