<?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>Ryan Sechrest</title>
	<atom:link href="http://ryansechrest.com/feed/" rel="self" type="application/rss+xml" />
	<link>http://ryansechrest.com</link>
	<description>St. Louis Web Developer &#38; User Interface Designer</description>
	<lastBuildDate>Wed, 09 May 2012 19:19:26 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.2</generator>
		<item>
		<title>WordPress hooks for saving, trashing, restoring, and deleting custom fields in a custom post type</title>
		<link>http://ryansechrest.com/2012/05/wordpress-hooks-for-saving-trashing-restoring-and-deleting-custom-fields-in-a-custom-post-type/</link>
		<comments>http://ryansechrest.com/2012/05/wordpress-hooks-for-saving-trashing-restoring-and-deleting-custom-fields-in-a-custom-post-type/#comments</comments>
		<pubDate>Wed, 09 May 2012 03:37:10 +0000</pubDate>
		<dc:creator>Ryan</dc:creator>
				<category><![CDATA[Code]]></category>
		<category><![CDATA[Insight]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Web]]></category>
		<category><![CDATA[custom post type]]></category>
		<category><![CDATA[hook]]></category>
		<category><![CDATA[plugin]]></category>
		<category><![CDATA[wordpress]]></category>

		<guid isPermaLink="false">http://ryansechrest.com/?p=358</guid>
		<description><![CDATA[This took me quite a while to figure out, but I finally determined what the proper hooks for managing custom fields in a custom post type in WordPress are. In my scenario, I have a custom post type that uses &#8230; <a href="http://ryansechrest.com/2012/05/wordpress-hooks-for-saving-trashing-restoring-and-deleting-custom-fields-in-a-custom-post-type/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>This took me quite a while to figure out, but I finally determined what the proper hooks for managing custom fields in a custom post type in WordPress are.</p>
<p>In my scenario, I have a custom post type that uses the <a title="Learn more about the WordPress function add_meta_box()" href="https://codex.wordpress.org/Function_Reference/add_meta_box" target="_blank"><code parse="no">add_meta_box()</code></a> function to add a few custom fields. As a matter of fact, those are the <em>only</em> fields available&#8230; the title, body, etc, have all been removed. Furthermore, I save those custom fields in a new table, because I need to perform additional actions outside of WordPress with that data, and storing them separately will make that a lot easier.</p>
<p>WordPress allows you to perform four actions with any post type, which meant I needed four hooks in order to keep the data in my table in sync with the status of the post. Those actions are: saving, moving something to the trash, restoring it from the trash, and permanently deleting.</p>
<p>It seems that WordPress is a bit inconsistent in the naming convention of those hooks, which is why it took some trial and error, but after spending some time with it, I&#8217;ve tested and confirmed the following four hooks to be the ones you need:</p>
<h2>Saving</h2>
<pre>add_action('save_post', 'custom_save_function');</pre>
<h2>Trashing</h2>
<pre>add_action('wp_trash_post', 'custom_trash_function');</pre>
<h2>Restoring</h2>
<pre>add_action('untrash_post', 'custom_restore_function');</pre>
<h2>Deleting</h2>
<pre>add_action('delete_post', 'custom_delete_function');</pre>
<p>Hooks that didn&#8217;t act the way I expected were: <code>trash_post</code>, <code>wp_untrash_post</code>, <code>trash_custom-post-type</code>, and <code>untrash_custom-post-type</code>. For instance, <code parse="no">trash_post</code> only worked with built-in post types, such as pages and posts, but <code parse="no">save_post</code> works even with custom post types.</p>
<p>Hopefully this two minute blog post will save someone some time, because those four hooks are pretty much necessary if you&#8217;re working with custom fields (unless you disable trash entirely and just permanently delete).</p>
<p>-RS</p>
]]></content:encoded>
			<wfw:commentRss>http://ryansechrest.com/2012/05/wordpress-hooks-for-saving-trashing-restoring-and-deleting-custom-fields-in-a-custom-post-type/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Change Firefox&#8217;s update release channel from esr to release</title>
		<link>http://ryansechrest.com/2012/05/change-firefoxs-update-release-channel-from-esr-to-release/</link>
		<comments>http://ryansechrest.com/2012/05/change-firefoxs-update-release-channel-from-esr-to-release/#comments</comments>
		<pubDate>Sun, 06 May 2012 19:55:13 +0000</pubDate>
		<dc:creator>Ryan</dc:creator>
				<category><![CDATA[Insight]]></category>
		<category><![CDATA[Software]]></category>
		<category><![CDATA[firefox]]></category>
		<category><![CDATA[update]]></category>

		<guid isPermaLink="false">http://ryansechrest.com/?p=352</guid>
		<description><![CDATA[I noticed today that my Secunia PSI was reporting that Firefox 11.0 was outdated. I went to Firefox &#62; About to check on that, but it was reporting that it was up to date. That&#8217;s when I noticed I was &#8230; <a href="http://ryansechrest.com/2012/05/change-firefoxs-update-release-channel-from-esr-to-release/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>I noticed today that my <a title="Learn more about Secunia PSI" href="https://secunia.com/products/consumer/psi/" target="_blank">Secunia PSI</a> was reporting that Firefox 11.0 was outdated. I went to <em>Firefox &gt; About</em> to check on that, but it was reporting that it was up to date. That&#8217;s when I noticed I was on the &#8220;esr&#8221; <a title="Learn more about Firefox's update channels" href="http://kb.mozillazine.org/Software_Update" target="_blank">update channel</a>, which is odd, because all the other Firefox installs I have on other computers are set to the &#8220;release&#8221; update channel. A quick Google search showed that there wasn&#8217;t a user-friendly way to change this, but it was nevertheless pretty straightforward.</p>
<p>The easiest way to change it is to browse to the following folder on your Windows computer: <em>&lt;installation directory&gt;\defaults\pref</em>. Your installation directory will most likely be either <em>Program Files</em> or <em>Program Files (x86)</em>. By the way, make sure Firefox is completely closed before doing this.</p>
<p>In that folder is a file called <em>channel-prefs.js</em>. Copy that file to your Desktop (select the file, press CTRL+C, go to your Desktop and press CTRL+V). Now open it with Notepad, which you can do by right-clicking on it, choosing open with, and then selecting Notepad.</p>
<p>Change the second line from:</p>
<pre>pref("app.update.channel", "esr");</pre>
<p>to:</p>
<pre>pref("app.update.channel", "release");</pre>
<p>Now save the file and close Notepad. Select the file on your Desktop and cut it (CTRL+X), then go back to your <em>pref</em> folder and press CTRL+V. Windows will ask you to confirm this, just press <em>Continue</em>.</p>
<p>Next time you launch Firefox and go back to Firefox &gt; About, you&#8217;ll see that you&#8217;re now on the &#8220;release&#8221; update channel and it will start downloading Firefox 12.0.</p>
<p>Let me know if you have any questions or problems!</p>
<p>PS: If you&#8217;ve read to use <em>about:config</em> to change the update release channel, this is deprecated and will no longer work.</p>
<p>-RS</p>
]]></content:encoded>
			<wfw:commentRss>http://ryansechrest.com/2012/05/change-firefoxs-update-release-channel-from-esr-to-release/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Taking a laptop apart to check out the CPU</title>
		<link>http://ryansechrest.com/2012/01/taking-a-laptop-apart-to-check-out-the-cpu/</link>
		<comments>http://ryansechrest.com/2012/01/taking-a-laptop-apart-to-check-out-the-cpu/#comments</comments>
		<pubDate>Sun, 08 Jan 2012 08:50:18 +0000</pubDate>
		<dc:creator>Ryan</dc:creator>
				<category><![CDATA[Personal]]></category>
		<category><![CDATA[cpu]]></category>
		<category><![CDATA[laptop]]></category>
		<category><![CDATA[motherboard]]></category>

		<guid isPermaLink="false">http://ryansechrest.com/?p=321</guid>
		<description><![CDATA[This was an old laptop that didn&#8217;t boot up anymore. Originally the diagnostic lights indicated it was a motherboard failure, but after researching it again and reading how other users solved this problem, I now came to the conclusion that &#8230; <a href="http://ryansechrest.com/2012/01/taking-a-laptop-apart-to-check-out-the-cpu/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>This was an old laptop that didn&#8217;t boot up anymore. Originally the diagnostic lights indicated it was a motherboard failure, but after researching it again and reading how other users solved this problem, I now came to the conclusion that perhaps it&#8217;s the CPU. I decided to take it apart and locate all the components. Now I know where everything is at and can easily swap pieces out. I keep those old computers around and check eBay every now and then for parts. Here are a few pictures of my adventure:</p>

<a href='http://ryansechrest.com/2012/01/taking-a-laptop-apart-to-check-out-the-cpu/20120107_212553/' title='20120107_212553'><img width="150" height="150" src="http://ryansechrest.com/wp-content/uploads/2012/01/20120107_212553-150x150.jpg" class="attachment-thumbnail" alt="20120107_212553" title="20120107_212553" /></a>
<a href='http://ryansechrest.com/2012/01/taking-a-laptop-apart-to-check-out-the-cpu/20120107_212601/' title='20120107_212601'><img width="150" height="150" src="http://ryansechrest.com/wp-content/uploads/2012/01/20120107_212601-150x150.jpg" class="attachment-thumbnail" alt="20120107_212601" title="20120107_212601" /></a>
<a href='http://ryansechrest.com/2012/01/taking-a-laptop-apart-to-check-out-the-cpu/20120107_212609/' title='20120107_212609'><img width="150" height="150" src="http://ryansechrest.com/wp-content/uploads/2012/01/20120107_212609-150x150.jpg" class="attachment-thumbnail" alt="20120107_212609" title="20120107_212609" /></a>
<a href='http://ryansechrest.com/2012/01/taking-a-laptop-apart-to-check-out-the-cpu/20120107_212644/' title='20120107_212644'><img width="150" height="150" src="http://ryansechrest.com/wp-content/uploads/2012/01/20120107_212644-150x150.jpg" class="attachment-thumbnail" alt="20120107_212644" title="20120107_212644" /></a>
<a href='http://ryansechrest.com/2012/01/taking-a-laptop-apart-to-check-out-the-cpu/20120107_212703/' title='20120107_212703'><img width="150" height="150" src="http://ryansechrest.com/wp-content/uploads/2012/01/20120107_212703-150x150.jpg" class="attachment-thumbnail" alt="20120107_212703" title="20120107_212703" /></a>
<a href='http://ryansechrest.com/2012/01/taking-a-laptop-apart-to-check-out-the-cpu/20120107_213437/' title='20120107_213437'><img width="150" height="150" src="http://ryansechrest.com/wp-content/uploads/2012/01/20120107_213437-150x150.jpg" class="attachment-thumbnail" alt="20120107_213437" title="20120107_213437" /></a>
<a href='http://ryansechrest.com/2012/01/taking-a-laptop-apart-to-check-out-the-cpu/20120107_213444/' title='20120107_213444'><img width="150" height="150" src="http://ryansechrest.com/wp-content/uploads/2012/01/20120107_213444-150x150.jpg" class="attachment-thumbnail" alt="20120107_213444" title="20120107_213444" /></a>
<a href='http://ryansechrest.com/2012/01/taking-a-laptop-apart-to-check-out-the-cpu/20120107_213912/' title='20120107_213912'><img width="150" height="150" src="http://ryansechrest.com/wp-content/uploads/2012/01/20120107_213912-150x150.jpg" class="attachment-thumbnail" alt="20120107_213912" title="20120107_213912" /></a>

<p>As you can see, I did find the CPU and therefore added a few eBay auctions to my watch list. Perhaps I can get one of those similar machines with heavy cosmetic damage, but an intact CPU that&#8217;s compatible with this model <img src='http://ryansechrest.com/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> </p>
<p>-RS</p>
]]></content:encoded>
			<wfw:commentRss>http://ryansechrest.com/2012/01/taking-a-laptop-apart-to-check-out-the-cpu/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Create a simple caching feature in your PHP script to cache your HTML output</title>
		<link>http://ryansechrest.com/2012/01/create-a-simple-caching-feature-in-your-php-script-to-cache-your-html-output/</link>
		<comments>http://ryansechrest.com/2012/01/create-a-simple-caching-feature-in-your-php-script-to-cache-your-html-output/#comments</comments>
		<pubDate>Wed, 04 Jan 2012 17:07:57 +0000</pubDate>
		<dc:creator>Ryan</dc:creator>
				<category><![CDATA[Code]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[cache]]></category>
		<category><![CDATA[cron job]]></category>
		<category><![CDATA[html]]></category>
		<category><![CDATA[script]]></category>
		<category><![CDATA[xml]]></category>

		<guid isPermaLink="false">http://ryansechrest.com/?p=303</guid>
		<description><![CDATA[Preface Every major site caches content in one way or another, whether it&#8217;d be entire pages, a subset of content, or only database queries. Having a caching system in place allows you to not only serve content to the user &#8230; <a href="http://ryansechrest.com/2012/01/create-a-simple-caching-feature-in-your-php-script-to-cache-your-html-output/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<h2>Preface</h2>
<p>Every major site <a title="Learn more about cache" href="https://en.wikipedia.org/wiki/Cache" target="_blank">caches</a> content in one way or another, whether it&#8217;d be entire pages, a subset of content, or only database queries. Having a caching system in place allows you to not only serve content to the user faster, but also reduces the strain on your server. The thing to remember is that just because you <em>can</em> cache content, doesn&#8217;t mean you should.</p>
<p>Let&#8217;s say you&#8217;re parsing a complex <a title="Learn more about XML" href="https://en.wikipedia.org/wiki/XML" target="_blank">XML</a> file and display its contents to the user, but the XML file only changes on a daily basis. If 100 users view that page and your server has to run that parsing script 100 times, it will have more of an impact on the server than sending back a static file. You may want to cache the results of the parsing script for 24 hours and then run the parsing script again to update the cache.</p>
<p>On the other hand, let&#8217;s say you&#8217;re running a daily deal website that displays a counter of how many users bought the deal. If you have a limited number of deals available, it&#8217;s in your and the user&#8217;s best interest to know when a deal has sold out. That number has to be pretty much up to date and you can&#8217;t reliably determine when to update a cache, so in that case, caching may not be desired.</p>
<p>Lastly, there&#8217;s something called triggers. My professor used to say that a computer in itself is pretty dumb and that it needs to be told exactly what to do. A cache doesn&#8217;t get updated unless something triggers it. If I want something to happen every 24 hours, for example, that&#8217;s what you&#8217;d use a <a title="Learn more about cron jobs" href="https://en.wikipedia.org/wiki/Cron" target="_blank">cron job</a> for, but in our instance, we only want to update the cache when someone is actually trying to retrieve the data and the cache is expired, so for our project below, the vistor will be the trigger.</p>
<h2>Project</h2>
<p>The goal is to build a simple caching feature into a script that will cache the results for a predefined duration.</p>
<h2>Requirements</h2>
<ul>
<li>Allow caching to be turned on and off.</li>
<li>Ability to set the cache&#8217;s duration before it expires.</li>
<li>Set a location on where the cache will be stored.</li>
</ul>
<h2>Solution</h2>
<p>When a user requests a page that contains the script, it will first check whether caching is enabled. If it is, it will check to see if a cached version already exists that can be displayed. If that is also true, it will compare the cache&#8217;s creation time with the current time and determine whether the cache is expired or not. If it is, it will execute the script and cache its content, but if it isn&#8217;t, it will display the cache to the user. If caching is turned off or the cache file doesn&#8217;t exist, the script will always execute the full script.</p>
<h2>Implementation</h2>
<p>First we&#8217;re going to setup a few variables to use in the script:</p>

<div class="bwp-syntax-block clearfix">
<div class="bwp-syntax-toolbar"><div class="bwp-syntax-control"><a href="javascript:;" class="bwp-syntax-source-switch" title="View Source Code"></a></div></div>
<div class="bwp-syntax-wrapper clearfix bwp-syntax-simple"><table class="php"><tbody><tr class="li1"><td class="ln"><pre class="de1">1
2
3
</pre></td><td class="de1"><pre class="de1"><span class="re0">$ENABLE_CACHE</span> <span class="sy0">=</span> <span class="kw4">true</span><span class="sy0">;</span>
<span class="re0">$CACHE_TIME_HOURS</span> <span class="sy0">=</span> <span class="nu0">12</span><span class="sy0">;</span>
<span class="re0">$CACHE_FILE_PATH</span> <span class="sy0">=</span> <span class="st_h">'./.cache/news.txt'</span><span class="sy0">;</span></pre></td></tr></tbody></table></div>
<div class="bwp-syntax-source"><pre class="no-parse">$ENABLE_CACHE = true;
$CACHE_TIME_HOURS = 12;
$CACHE_FILE_PATH = './.cache/news.txt';</pre></div></div>

<ul>
<li>On <span style="color: #ff6600;">line 1</span> we have a bool (<code parse="no">true</code>/<code parse="no">false</code>) that determines whether caching should be on or off.</li>
<li>On <span style="color: #ff6600;">line 2</span> we&#8217;ll use an integer that tells the script after how many hours the cache is expired.</li>
<li>On <span style="color: #ff6600;">line 3</span> is a string that indicates the path and filename of the cache file. Make sure that directory is writable by apache. Also notice that I created a new folder called &#8220;.cache&#8221; that begins with a period. I do that for two reaons: (1) all folders with a symbol, such as a period, are sorted higher than the other folders, so I can find it easily and (2) a folder with a period is a system folder to me, which means it should never be directly accessed by the public. By the way, the &#8220;./&#8221; at the beginning of the string means &#8220;this directory&#8221; and refers to the directory the script is executing from — it&#8217;s a relative path.</li>
</ul>
<p>Now that we have our variables, let&#8217;s write a condition in which to display the cache:</p>

<div class="bwp-syntax-block clearfix">
<div class="bwp-syntax-toolbar"><div class="bwp-syntax-control"><a href="javascript:;" class="bwp-syntax-source-switch" title="View Source Code"></a></div></div>
<div class="bwp-syntax-wrapper clearfix bwp-syntax-simple"><table class="php"><tbody><tr class="li1"><td class="ln"><pre class="de1">1
2
3
4
5
</pre></td><td class="de1"><pre class="de1"><span class="kw1">if</span><span class="br0">&#40;</span><span class="re0">$ENABLE_CACHE</span> <span class="sy0">&amp;&amp;</span> <span class="kw3">file_exists</span><span class="br0">&#40;</span><span class="re0">$CACHE_FILE_PATH</span><span class="br0">&#41;</span> <span class="sy0">&amp;&amp;</span> <span class="br0">&#40;</span><span class="kw3">time</span><span class="br0">&#40;</span><span class="br0">&#41;</span> <span class="sy0">-</span> <span class="kw3">filemtime</span><span class="br0">&#40;</span><span class="re0">$CACHE_FILE_PATH</span><span class="br0">&#41;</span> <span class="sy0">&lt;</span> <span class="br0">&#40;</span><span class="re0">$CACHE_TIME_HOURS</span> <span class="sy0">*</span> <span class="nu0">60</span> <span class="sy0">*</span> <span class="nu0">60</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span>
&nbsp; <span class="co1">// display cache</span>
<span class="br0">&#125;</span> <span class="kw1">else</span> <span class="br0">&#123;</span>
&nbsp; <span class="co1">// run script and save cache</span>
<span class="br0">&#125;</span></pre></td></tr></tbody></table></div>
<div class="bwp-syntax-source"><pre class="no-parse">if($ENABLE_CACHE &amp;&amp; file_exists($CACHE_FILE_PATH) &amp;&amp; (time() - filemtime($CACHE_FILE_PATH) &lt; ($CACHE_TIME_HOURS * 60 * 60))) {
	// display cache
} else {
	// run script and save cache
}</pre></div></div>

<ul>
<li>On <span style="color: #ff6600;">line 1</span> we do the following checks: if the variable <code parse="no">$ENABLE_CACHE</code> is set to <code parse="no">true</code>, and the file at <code parse="no">./.cache/news.txt</code> exists, and the current time (let&#8217;s say 1/4/12 4:00pm) minus the file&#8217;s creation time (let&#8217;s say 1/4/12 3:00pm) — which equals 1 hour — is less than 12 hours (1 is less than 12), then display the cache.</li>
</ul>
<p>Let&#8217;s complete the script as follows:</p>

<div class="bwp-syntax-block clearfix">
<div class="bwp-syntax-toolbar"><div class="bwp-syntax-control"><a href="javascript:;" class="bwp-syntax-source-switch" title="View Source Code"></a></div></div>
<div class="bwp-syntax-wrapper clearfix bwp-syntax-simple"><table class="php"><tbody><tr class="li1"><td class="ln"><pre class="de1">1
2
3
4
5
6
7
8
9
10
11
</pre></td><td class="de1"><pre class="de1"><span class="re0">$ENABLE_CACHE</span> <span class="sy0">=</span> <span class="kw4">true</span><span class="sy0">;</span>
<span class="re0">$CACHE_TIME_HOURS</span> <span class="sy0">=</span> <span class="nu0">12</span><span class="sy0">;</span>
<span class="re0">$CACHE_FILE_PATH</span> <span class="sy0">=</span> <span class="st_h">'./.cache/news.txt'</span><span class="sy0">;</span>
&nbsp;
<span class="kw1">if</span><span class="br0">&#40;</span><span class="re0">$ENABLE_CACHE</span> <span class="sy0">&amp;&amp;</span> <span class="kw3">file_exists</span><span class="br0">&#40;</span><span class="re0">$CACHE_FILE_PATH</span><span class="br0">&#41;</span> <span class="sy0">&amp;&amp;</span> <span class="br0">&#40;</span><span class="kw3">time</span><span class="br0">&#40;</span><span class="br0">&#41;</span> <span class="sy0">-</span> <span class="kw3">filemtime</span><span class="br0">&#40;</span><span class="re0">$CACHE_FILE_PATH</span><span class="br0">&#41;</span> <span class="sy0">&lt;</span> <span class="br0">&#40;</span><span class="re0">$CACHE_TIME_HOURS</span> <span class="sy0">*</span> <span class="nu0">60</span> <span class="sy0">*</span> <span class="nu0">60</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span>
&nbsp; <span class="kw1">echo</span> <span class="sy0">@</span><span class="kw3">file_get_contents</span><span class="br0">&#40;</span><span class="re0">$CACHE_FILE_PATH</span><span class="br0">&#41;</span><span class="sy0">;</span>
<span class="br0">&#125;</span> <span class="kw1">else</span> <span class="br0">&#123;</span>
&nbsp; <span class="co1">// your script runs here and the result is stored in a variable called $output</span>
&nbsp; <span class="sy0">@</span><span class="kw3">file_put_contents</span><span class="br0">&#40;</span><span class="re0">$CACHE_FILE_PATH</span><span class="sy0">,</span> <span class="re0">$output</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; <span class="kw1">echo</span> <span class="re0">$output</span><span class="sy0">;</span>
<span class="br0">&#125;</span></pre></td></tr></tbody></table></div>
<div class="bwp-syntax-source"><pre class="no-parse">$ENABLE_CACHE = true;
$CACHE_TIME_HOURS = 12;
$CACHE_FILE_PATH = './.cache/news.txt';

if($ENABLE_CACHE &amp;&amp; file_exists($CACHE_FILE_PATH) &amp;&amp; (time() - filemtime($CACHE_FILE_PATH) &lt; ($CACHE_TIME_HOURS * 60 * 60))) {
	echo @file_get_contents($CACHE_FILE_PATH);
} else {
	// your script runs here and the result is stored in a variable called $output
	@file_put_contents($CACHE_FILE_PATH, $output);
	echo $output;
}</pre></div></div>

<ul>
<li>On <span style="color: #ff6600;">line 6</span> I use an <a title="Learn more about error control operators" href="http://php.net/manual/en/language.operators.errorcontrol.php" target="_blank">@ sign to suppress any errors</a> (error control operator).</li>
<li>On <span style="color: #ff6600;">line 8</span> is where you would do your XML parsing and then store the output in a variable called <code parse="no">$output</code>.</li>
<li>On <span style="color: #ff6600;">line 9</span> you save the entire output to the file.</li>
<li>On <span style="color: #ff6600;">line 10</span> you display all of the output on the screen.</li>
</ul>
<h2>Conclusion</h2>
<p>As you can see, in its simplest form, it&#8217;s quite easy to implement. Now, if you had multiple scripts that required the caching of data, you might want to create functions or even an object class and with member functions, so that you can streamline changes, but I&#8217;ll save that for another how-to.</p>
<p>If you have any questions or comments, as always, feel free to leave them below.</p>
<p>-RS</p>
]]></content:encoded>
			<wfw:commentRss>http://ryansechrest.com/2012/01/create-a-simple-caching-feature-in-your-php-script-to-cache-your-html-output/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Top 3 Firefox add-ons for security enthusiasts in 2012</title>
		<link>http://ryansechrest.com/2012/01/top-3-firefox-add-ons-for-security-enthusiasts-in-2012/</link>
		<comments>http://ryansechrest.com/2012/01/top-3-firefox-add-ons-for-security-enthusiasts-in-2012/#comments</comments>
		<pubDate>Sun, 01 Jan 2012 20:16:31 +0000</pubDate>
		<dc:creator>Ryan</dc:creator>
				<category><![CDATA[Insight]]></category>
		<category><![CDATA[Software]]></category>
		<category><![CDATA[add-ons]]></category>
		<category><![CDATA[firefox]]></category>
		<category><![CDATA[https everywhere]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[noscript]]></category>
		<category><![CDATA[security]]></category>
		<category><![CDATA[web of trust]]></category>

		<guid isPermaLink="false">http://ryansechrest.com/?p=295</guid>
		<description><![CDATA[Security is time consuming and often just plain inconvenient, but there are a handful of plugins that make being secure much easier. I give you the top 3 security add-ons for Firefox that I personally use. (PS: In terms of &#8230; <a href="http://ryansechrest.com/2012/01/top-3-firefox-add-ons-for-security-enthusiasts-in-2012/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Security is time consuming and often just plain inconvenient, but there are a handful of plugins that make being secure much easier. I give you the top 3 security add-ons for Firefox that I personally use.</p>
<p>(PS: In terms of ratings, 1/5 refers to the least and 5/5 to the most.)</p>
<h2>1. <a title="Learn more about HTTPS Everywhere" href="https://www.eff.org/https-everywhere" target="_blank">HTTPS Everywhere</a></h2>
<p><strong>Easy of use</strong>: <span style="color: #0000ff;"><strong>5/5</strong></span>, <strong>Convenience</strong>:<span style="color: #0000ff;"> <strong>5/5</strong></span></p>
<p>This plugins basically has a list of popular sites programmed in it, such as Facebook, Twitter, Google, etc. that offer a secure <a title="Learn more about https" href="http://www.instantssl.com/ssl-certificate-products/https.html" target="_blank">https</a> connection. Whenever you visit one of those sites, it forces Firefox to use the secure connection instead of the standard (http) one. Https is a protocol that encrypts data between you and the website you&#8217;re interacting with. If you were wondering what the little &#8220;s&#8221; after http stands for, the answer is &#8220;secure&#8221; <img src='http://ryansechrest.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' />  .</p>
<p>The only note I have about this is that one of the websites on that list is Netflix, and even though Netflix supports logging in securely, it doesn&#8217;t properly work when trying to manage your queue, so you may have to disable it just for that site. Other sites may exhibit problems as well, but I haven&#8217;t come across any of them yet.</p>
<h2>2. <a title="Learn more about NoScript" href="https://addons.mozilla.org/en-US/firefox/addon/noscript/" target="_blank">NoScript</a></h2>
<p><strong>Easy of use</strong>: <span style="color: #0000ff;"><strong>4/5</strong></span>, <strong>Convenience</strong>: <span style="color: #0000ff;"><strong>3/5</strong></span></p>
<p>This plugin is a lifesaver. Most malicious things on a website, whether it&#8217;s a <a title="Learn more about fake security warnings" href="http://www.microsoft.com/security/pc-security/antivirus-rogue.aspx" target="_blank">fake security warning</a> that your PC is infected or something that tries to <a title="Learn more about what hijacking a browser is" href="http://www.microsoft.com/security/resources/hijacking-whatis.aspx" target="_blank">hijack your browser</a>, are created by using scripts, or more specifically, <a title="Learn about what JavaScript is" href="https://en.wikipedia.org/wiki/JavaScript" target="_blank">JavaScript</a>. This add-on basically prevents <em>all</em> scripts from executing without explicit permission from you. The problem is, most websites use and rely on scripts. Scripts in themselves aren&#8217;t dangerous at all, they are quite useful, it just depends on what they do. So blocking all scripts on all websites is not the solution.</p>
<p>The purpose of the add-on is to block them by default and then you specifically allow the scripts you need. This sounds very complicated and it is at first, but after a while you&#8217;ll be able to recognize what seems legitimate and what not. My approach is this: I try to use a website the best I can without scripts. If something doesn&#8217;t work, I enable the most obvious ones first. If I&#8217;m on Yahoo!&#8217;s website for example, I&#8217;ll enable scripts from yahoo.com first, then try it again, and if it still doesn&#8217;t work, I&#8217;ll enable other scripts. I&#8217;ll probably have to create another post down the road that explains what the &#8220;other scripts&#8221; are in more detail.</p>
<p>In it&#8217;s most simplest form, if you don&#8217; know anything about scripts, enable them all on the sites you trust, however, often you&#8217;ll find yourself googling a topic of interest and you may visit many unfamiliar and untrusted websites when following those search results. For those sites, always block all scripts. If the site doesn&#8217;t come up or something looks weird, leave the site and try another result.</p>
<h2>3. <a title="Learn more about Web of Trust" href="https://addons.mozilla.org/en-US/firefox/addon/wot-safe-browsing-tool/" target="_blank">Web of Trust (WOT)</a></h2>
<p><strong>Easy of use</strong>: <span style="color: #0000ff;"><strong>5/5</strong></span>, <strong>Convenience</strong>: <span style="color: #0000ff;"><strong>5/5</strong></span></p>
<p>How great would it be to know whether a website is dangerous or not <em>before</em> you visit it? Imagine a little circle next to all links that could have one of three colors: green (this website is safe), yellow (this website may be suspicious), and red (this website is dangerous). Would be awesome, right? Well, someone&#8217;s thought of that.</p>
<p>I give you the Web of Trust add-on. That&#8217;s exactly what it does. With it installed, for example, you&#8217;ll see little colored circles on all the links in a Google search result and that will tell you whether you should go to that website or not. On top of that, even if you click on a website that doesn&#8217;t have a circle and it was rated dangerously or maybe it was red and you accidentally clicked it, an intermediate screen will appear asking you to confirm whether you really want to visit that website or not. The great thing is that WOT is community based, so it takes other people&#8217;s reviews in consideration when rating websites.</p>
<p>Sometimes sites aren&#8217;t rated (like this one here), which is indicated by a gray circle and a question mark. It&#8217;s up to you whether you want to visit it or try another site.</p>
<p>There you have it, the 3 best add-ons for Firefox in terms of security. If I missed something or there&#8217;s another great add-on you can recommend, leave it in the comments below.</p>
<p>-RS</p>
]]></content:encoded>
			<wfw:commentRss>http://ryansechrest.com/2012/01/top-3-firefox-add-ons-for-security-enthusiasts-in-2012/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>5 best Firefox add-ons for web developers in 2012</title>
		<link>http://ryansechrest.com/2011/12/5-best-firefox-add-ons-for-web-developers-in-2012/</link>
		<comments>http://ryansechrest.com/2011/12/5-best-firefox-add-ons-for-web-developers-in-2012/#comments</comments>
		<pubDate>Wed, 28 Dec 2011 23:34:25 +0000</pubDate>
		<dc:creator>Ryan</dc:creator>
				<category><![CDATA[Insight]]></category>
		<category><![CDATA[Software]]></category>
		<category><![CDATA[add-ons]]></category>
		<category><![CDATA[colorzilla]]></category>
		<category><![CDATA[firebug]]></category>
		<category><![CDATA[firefox]]></category>
		<category><![CDATA[fireshot]]></category>
		<category><![CDATA[web developer]]></category>
		<category><![CDATA[worldip]]></category>

		<guid isPermaLink="false">http://ryansechrest.com/?p=284</guid>
		<description><![CDATA[The only things I ever recommend are things that I use myself and that have proven themselves over time. I&#8217;ve used the following add-ons at least weekly, if not daily, throughout 2011, which is how they&#8217;ve landed on my list &#8230; <a href="http://ryansechrest.com/2011/12/5-best-firefox-add-ons-for-web-developers-in-2012/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>The only things I ever recommend are things that I use myself and that have proven themselves over time. I&#8217;ve used the following add-ons at least weekly, if not daily, throughout 2011, which is how they&#8217;ve landed on my list of top 5 Firefox add-ons for 2012.</p>
<h2>1. <a title="Learn more about ColorZilla" href="https://addons.mozilla.org/en-us/firefox/addon/colorzilla/" target="_blank">ColorZilla</a></h2>
<p><strong>Purpose</strong>: This add-on adds a little eyedropper icon after your Firefox search bar. If you click it, you can sample any color on a webpage.</p>
<p><strong>Usage</strong>: I use it to sample a color on a webpage and it automatically copies the hex value so I can use it in a stylesheet (CSS) file.</p>
<h2>2. <a title="Learn more about Firebug" href="https://addons.mozilla.org/en-us/firefox/addon/firebug/" target="_blank">Firebug</a></h2>
<p><strong>Purpose</strong>: To inspect HTML, CSS, and JavaScript code on a webpage, view any connections that are initiated and their response, and see the variables currently loaded in the DOM. You can activate the window via the F12 key (Windows).</p>
<p><strong>Usage</strong>: I mostly use it to inspect and manipulate elements on a webpage. For example, right-click anywhere and select &#8220;Inspect element&#8221;. Firebug will jump right to the code and you can alter the HTML on the left and the CSS on the right. This makes tweaking styles and duplicating content very easy. Furthermore, I use it to monitor AJAX responses on the &#8220;Net&#8221; tab, which tells me whether I get the expected results or not.</p>
<h2>3. <a title="Learn more about FireShot" href="https://addons.mozilla.org/en-US/firefox/addon/fireshot/" target="_blank">FireShot</a></h2>
<p><strong>Purpose</strong>: To take screenshots of a full, partial, or custom area on a webpage.</p>
<p><strong>Usage</strong>: Often I&#8217;m asked to show a demo of a webpage in a meeting or perhaps a client is asking for it via email. FireShot adds a little bar in the status bar of Firefox, which gives me an icon to select either a full page screenshot (from top to bottom), a partial screenshot (anything that&#8217;s viewable without scrolling), or I can drag a custom rectangle over the area I want. I can then save the image or copy it to my clipboard.</p>
<h2>4. <a title="Learn more about Web Developer" href="https://addons.mozilla.org/en-US/firefox/addon/web-developer/" target="_blank">Web Developer</a></h2>
<p><strong>Purpose</strong>: It lets you modify how your webpage will be rendered in your browser and provides tools to work with images and elements on a webpage.</p>
<p><strong>Usage</strong>: This add-on does a lot, but I only use a subset of features. I use it for turning off JavaScript on a webapge (Disable &gt; JavaScript &gt; All), deleting or disabling cookies (Cookies &gt; Disable Cookies &gt; All Cookies), getting a div&#8217;s size (Information &gt; Display Element Information&#8230; click on a page element), and to measure something on a webpage (Miscellaneous &gt; Display Ruler&#8230; click and drag with mouse to create a box).</p>
<h2>5. <a title="Learn more about WorldIP" href="https://addons.mozilla.org/en-US/firefox/addon/worldip-flag-and-datacenter-pi/" target="_blank">WorldIP</a></h2>
<p><strong>Purpose</strong>: Displays server&#8217;s location, IP address, provider, and your IP address.</p>
<p><strong>Usage</strong>: I work with many different servers at a time and sometimes I move websites around. This little add-on tells me where the current website is located, its IP address, and who it&#8217;s hosted with. When I&#8217;m not using it for my stuff, I just find it interesting to see where everyone host&#8217;s their website <img src='http://ryansechrest.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' />  .</p>
<p>There you have it, the 5 best Firefox add-ons for me in 2012. If you have something you use a lot that makes your life easier, feel free to share it in the comments below.</p>
<p>-RS</p>
]]></content:encoded>
			<wfw:commentRss>http://ryansechrest.com/2011/12/5-best-firefox-add-ons-for-web-developers-in-2012/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Firefox 9 uses significantly less memory</title>
		<link>http://ryansechrest.com/2011/12/firefox-9-uses-significantly-less-memory/</link>
		<comments>http://ryansechrest.com/2011/12/firefox-9-uses-significantly-less-memory/#comments</comments>
		<pubDate>Thu, 22 Dec 2011 15:44:14 +0000</pubDate>
		<dc:creator>Ryan</dc:creator>
				<category><![CDATA[Insight]]></category>
		<category><![CDATA[News]]></category>
		<category><![CDATA[Software]]></category>
		<category><![CDATA[bug]]></category>
		<category><![CDATA[firefox]]></category>
		<category><![CDATA[memory]]></category>

		<guid isPermaLink="false">http://ryansechrest.com/?p=279</guid>
		<description><![CDATA[I received an update for Firefox 9 today and I&#8217;m very pleased with its improved memory (RAM) management. Firefox used an average of 600,000 K for about ten open tabs, however, since the new release of version 9, we&#8217;re now &#8230; <a href="http://ryansechrest.com/2011/12/firefox-9-uses-significantly-less-memory/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>I received an update for <a title="Download Firefox 9 from Mozilla" href="http://www.mozilla.com/firefox/" target="_blank">Firefox 9</a> today and I&#8217;m very pleased with its improved memory (RAM) management. Firefox used an average of 600,000 K for about ten open tabs, however, since the new release of version 9, we&#8217;re now down to an average of 200,000 K. I&#8217;m not even interested to see what other improvements they made, because quite frankly, this is the big one I&#8217;ve been waiting for. So, if you are like me and have dabbled in other browsers, such as Chrome, Opera, etc. since then, it&#8217;s safe to say that Firefox is back!</p>
<p>Here are some of the memory related <a title="Bugs that were fixed in Firefox 9" href="https://www.mozilla.org/en-US/firefox/9.0.1/releasenotes/buglist.html" target="_blank">bugs that were fixed</a>:</p>
<ul>
<li><a href="https://bugzilla.mozilla.org/show_bug.cgi?id=669815">669815</a> Type inference uses too much memory</li>
<li><a href="https://bugzilla.mozilla.org/show_bug.cgi?id=646913">646913</a> Massive memory usage when viewing www.cnn.com</li>
<li><a href="https://bugzilla.mozilla.org/show_bug.cgi?id=678997">678997</a> memory leak in widget/src/android/AndroidBridge.cpp</li>
<li><a href="https://bugzilla.mozilla.org/show_bug.cgi?id=148636">148636</a> Enormous memory usage rendering with lots of form elements</li>
<li><a href="https://bugzilla.mozilla.org/show_bug.cgi?id=124608">124608</a> Imagelib memory usage issues</li>
<li><a href="https://bugzilla.mozilla.org/show_bug.cgi?id=503108" target="_blank">503108</a> Memory usage climbs slowly but continuously on downloadstats.mozilla.com</li>
</ul>
<p>-RS</p>
]]></content:encoded>
			<wfw:commentRss>http://ryansechrest.com/2011/12/firefox-9-uses-significantly-less-memory/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Validating user input with PHP: methods, data, and its applications</title>
		<link>http://ryansechrest.com/2011/12/validating-user-input-with-php-methods-data-and-its-applications/</link>
		<comments>http://ryansechrest.com/2011/12/validating-user-input-with-php-methods-data-and-its-applications/#comments</comments>
		<pubDate>Thu, 15 Dec 2011 15:38:00 +0000</pubDate>
		<dc:creator>Ryan</dc:creator>
				<category><![CDATA[Code]]></category>
		<category><![CDATA[Insight]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Web]]></category>
		<category><![CDATA[browser headers]]></category>
		<category><![CDATA[cookies]]></category>
		<category><![CDATA[data]]></category>
		<category><![CDATA[database]]></category>
		<category><![CDATA[display]]></category>
		<category><![CDATA[form]]></category>
		<category><![CDATA[http]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[mysql]]></category>
		<category><![CDATA[query string]]></category>
		<category><![CDATA[url]]></category>
		<category><![CDATA[user input]]></category>
		<category><![CDATA[validation]]></category>

		<guid isPermaLink="false">http://ryansechrest.com/?p=222</guid>
		<description><![CDATA[If you&#8217;ve ever read any kind of article that talks about sanitizing, filtering, cleaning, escaping, or validating user input, I&#8217;m sure you&#8217;ve come across this line: don&#8217;t trust it — ever! Before you can protect yourself from unwanted data, injections, &#8230; <a href="http://ryansechrest.com/2011/12/validating-user-input-with-php-methods-data-and-its-applications/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>If you&#8217;ve ever read any kind of article that talks about sanitizing, filtering, cleaning, escaping, or validating user input, I&#8217;m sure you&#8217;ve come across this line: <strong>don&#8217;t trust it</strong> — <em>ever</em>! Before you can protect yourself from unwanted data, injections, script crashes, and the like, you&#8217;d be smart to follow the next three steps to ensure that you understand the methods, data, and its applications.</p>
<ol>
<li><strong>I</strong><strong>dentify all areas that allow for user input</strong>. In other words, what <em>can</em> the user manipulate? It&#8217;s not necessarily just the form field you provided for them to fill out, but maybe a piece of data that you&#8217;re passing in via a <a title="Learn more about query strings from Wikipedia" href="https://en.wikipedia.org/wiki/Query_string" target="_blank">query string</a>, a hidden form field, or a <a title="List of browser headers from Wikipedia" href="https://en.wikipedia.org/wiki/List_of_HTTP_header_fields" target="_blank">browser header</a>.</li>
<li><strong>Determine what is valid input</strong>. The more specific you are in asking for a piece of data, the more granular you can be when it comes to validating. For example, instead of loosely asking for an address, you&#8217;d ask for the street, city, state, and zip code, which allows you to validate each piece of data separately.</li>
<li><strong>Understand how you&#8217;re going to use that data</strong>. Whether you display it back on the screen, pass it to another program, or simply store it in a database, each application has its specific needs and requirements. For example, if you display data with HTML code on the screen, you won&#8217;t see the code, you&#8217;ll see the rendered version — which may or may not be desired — but if you&#8217;re storing this data in the database, you&#8217;d be OK.</li>
</ol>
<p>After you&#8217;ve asked yourself those questions and thought about your data, you&#8217;ll have a good idea on where to start, but just knowing the concept won&#8217;t help you with implementation, so let&#8217;s take a closer look at each of these.</p>
<h2>1. Identify all areas that allow for user input</h2>
<p>There are a lot of places a user can change your data, so the best way to look at it is so: if you&#8217;re using a piece of data that you did not create and are not in control of every step of the way, you need to validate it. As a side note, filtering, validating, and escaping data are technically speaking three different things, but for simplicity sake, when I refer to validatation, I&#8217;m really refering to some or all of those aspects.</p>
<p>Let&#8217;s take a look at how you might receive user controllable data:</p>
<ul>
<li><strong>Form fields</strong>: these are the most obvious of all, because you&#8217;re directly asking the user for data.</li>
<li><strong>Hidden form fields</strong>: even though the average user doesn&#8217;t see those fields, anyone can easily alter the contents of them. So make sure to double check that data before you use it and verify that your script gracefully halts if that piece of data is missing or invalid.</li>
<li><a title="Learn more about HTTP cookies form Wikipedia" href="https://en.wikipedia.org/wiki/HTTP_cookie" target="_blank"><strong>Cookies</strong></a>: if you ever store data in a cookie, you need to double check that the value inside has not been altered and doesn&#8217;t contain anything that might cause your script to break.</li>
<li><strong>Query strings</strong>: if your application relies on reading information from the URL, you also need to check that the values you grab are valid. If you&#8217;re using a value as an ID number to make a database query, it&#8217;s a good idea to ensure that the value truly consists of digits.</li>
<li><strong>JavaScript</strong>: on occasion you may use JavaScript on your page to pass in a query string or POST data to your script, so keep that in mind before using that particular data.</li>
<li><strong>Browser headers</strong>: sometimes an application uses information from the user&#8217;s browser, such as the referer or user agent, so it&#8217;s important to remember that this data can be manipulated as well.</li>
<li><strong>Responses</strong>: if your script receives data from other applications or servers that you don&#8217;t control, that would also be considered user input. For example, maybe you&#8217;re parsing an <a title="Learn more about RSS from Wikipedia" href="https://en.wikipedia.org/wiki/RSS" target="_blank">RSS</a> feed or work with <a title="Learn more about JSON" href="http://www.json.org/" target="_blank">JSON</a> reponses.</li>
</ul>
<p>Checking the above does several things for you:</p>
<ul>
<li>It reduces the risk of your application being used for illicit purposes e.g. compromising your database or sending spam email.</li>
<li>It provides you with more control over the data that enters your system e.g. ensuring that a phone number is really a phone number.</li>
<li>It allows you to be more efficient in processing the data e.g. if you look up a product in the database via its ID number, but you notice the ID number consists of letters as apposed to a number, there&#8217;s no need to make a database query in the first place.</li>
</ul>
<h2>2. Determine what is valid input</h2>
<p>This is a pretty tricky subject, because if you&#8217;re too specific, you might miss a scenario where perfectly valid data is rejected, but if you&#8217;re too unrestrictive, you&#8217;ll get data that&#8217;s not useful. Some of the things you can control are the length of characters — you should always set a limit — ranges e.g. a number between zero and fifty, and their data type e.g. a number or a string. You can validate input by using some of <a title="Learn more about PHP" href="http://php.net/" target="_blank">PHP</a>&#8216;s built-in functions like <a title="PHP function to check for a digit" href="http://us.php.net/manual/en/function.is-int.php" target="_blank">is_int</a>, <a title="PHP function to check for alphabetic characters" href="http://us.php.net/manual/en/function.ctype-alpha.php" target="_blank">ctype_alpha</a>, <a title="PHP function to check for alphanumeric characters" href="http://us.php.net/manual/en/function.ctype-alnum.php" target="_blank">ctype_alnum</a>, or something more custom like a <a title="PHP function for supplying a regular expression" href="http://php.net/manual/en/function.preg-match.php" target="_blank">regular expression</a> or a <a title="Create a user-defined PHP function" href="http://php.net/manual/en/function.preg-match.php" target="_blank">user-defined function</a>.</p>
<p>In addition, there are two approaches to validating user input: inclusive and exclusive. Inclusive means that you specifically tell your application what is acceptable input, and exclusive let&#8217;s you specify the kind of data you don&#8217;t want.</p>
<p>An inclusive example would be to say that you want a number greater than zero, but less than fifty. You&#8217;re telling the system what to expect. The exclusive version would state that a number less than zero or greater than fifty is unacceptable. Here you told the system what to prevent. A different example would be checking that a phone number consists of only digits, parenthesis, or hyphens (inclusive) versus ensuring that the phone number doesn&#8217;t contain any letters or other symbols (exclusive).</p>
<p>Most of the time you&#8217;ll probably end up using a combination of the two, depending on whichever scenario is easier to test.</p>
<h2>3. Understand how you&#8217;re going to use that data</h2>
<p>Here are several ways your data can be used and what the best practices are for working with such data:</p>
<ol>
<li><strong>Database</strong>: if you&#8217;re planning on storing the data in a database, you need to escape it. Different database languages may have different ways of escaping, so pay attention to which one you&#8217;re using, but for <a title="Open source database system" href="https://www.mysql.com/" target="_blank">MySQL</a>, which is a popular and open source <a title="Learn more about what a RDBMS is from Wikipedia" href="https://en.wikipedia.org/wiki/Relational_database_management_system" target="_blank">relational database management system</a> (RDBMS), any data must pass through the <a title="Learn how to use the mysql_real_escape_string() PHP function" href="http://php.net/manual/en/function.mysql-real-escape-string.php" target="_blank">mysql_real_escape_string() PHP function</a>. It protects your database from injections.</li>
<li><strong>Display</strong>: if you&#8217;re going to display user supplied data on your website, you should pass it through <a title="Learn more about PHP's htmlspecialchars() function" href="http://php.net/manual/en/function.htmlspecialchars.php" target="_blank">PHP&#8217;s htmlspecialchars() function</a>. It protects your website from <a title="Learn about cross-site scripting from Wikipedia" href="https://en.wikipedia.org/wiki/Cross-site_scripting" target="_blank">cross-site scripting</a> (XSS).</li>
<li><strong>URL</strong>: it&#8217;s possible that you need to send or save data from a user in the URL. If that&#8217;s the case, everything should pass through the <a title="Learn more about the urlencode() PHP function" href="http://php.net/manual/en/function.urlencode.php" target="_blank">urlencode() PHP function</a>. This ensures that your URL remains valid.</li>
<li><strong>Files</strong>: perhaps you&#8217;re saving information in a log file. Generally speaking, you can store it anyway you want, but if you know which method you&#8217;ll be using to read that data, you should store it accordingly. If the file&#8217;s contents will be displayed on the screen, use method #2 described above.</li>
<li><strong>Transmission</strong>: sometimes you may be sending data from one server or application to another. You should validate your data before transmission appropriately and if you&#8217;re on the receiver&#8217;s end, you should validate it again to ensure that it hasn&#8217;t been modified somewhere in between. It&#8217;s similar to the concept of <a title="Learn more about the loose coupling concept from Wikipedia" href="https://en.wikipedia.org/wiki/Loose_coupling" target="_blank">loose coupling</a>, where each system is unaware of what the other system is doing, therefore you can&#8217;t assume that it has been validated on the other end.</li>
</ol>
<p>The purpose of this article was to give you an idea of the methods, data, and its application in systems. There are exceptions to every rule, but now that you know what&#8217;s possible and how things are commonly utilized, you have the knowledge to take that and apply it to your own specific project.</p>
<p>If you have suggestions or questions, feel free to leave comments below.</p>
<p>-RS</p>
]]></content:encoded>
			<wfw:commentRss>http://ryansechrest.com/2011/12/validating-user-input-with-php-methods-data-and-its-applications/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Android email application bug: unable to delete email messages</title>
		<link>http://ryansechrest.com/2011/12/android-email-application-bug-unable-to-delete-email-messages/</link>
		<comments>http://ryansechrest.com/2011/12/android-email-application-bug-unable-to-delete-email-messages/#comments</comments>
		<pubDate>Tue, 13 Dec 2011 23:01:37 +0000</pubDate>
		<dc:creator>Ryan</dc:creator>
				<category><![CDATA[Insight]]></category>
		<category><![CDATA[Software]]></category>
		<category><![CDATA[android]]></category>
		<category><![CDATA[bug]]></category>
		<category><![CDATA[delete]]></category>
		<category><![CDATA[email]]></category>
		<category><![CDATA[galaxy]]></category>
		<category><![CDATA[samsung]]></category>

		<guid isPermaLink="false">http://ryansechrest.com/?p=213</guid>
		<description><![CDATA[Today I noticed something interesting on my Samsung Galaxy S2 aka. Epic 4G Touch: I&#8217;m unable to delete email messages using Android&#8217;s stock email application. I did a bit of research and it&#8217;s definitely a bug. There are at least &#8230; <a href="http://ryansechrest.com/2011/12/android-email-application-bug-unable-to-delete-email-messages/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Today I noticed something interesting on my Samsung Galaxy S2 aka. Epic 4G Touch: I&#8217;m unable to delete email messages using Android&#8217;s stock email application.</p>
<p>I did a bit of research and it&#8217;s definitely a bug. There are at least four bug reports I could find on <a title="Google's Android project" href="https://code.google.com/p/android/" target="_blank">Google&#8217;s Android project</a>:</p>
<ol>
<li><a title="Bug report 12282 IMAP email deletion not working" href="https://code.google.com/p/android/issues/detail?id=12282&amp;can=5&amp;colspec=ID%20Type%20Status%20Owner%20Summary%20Stars" target="_blank">12282 <span class="h3">IMAP email deletion not working</span></a></li>
<li><a title="Bug report 13195 Certain emails reappear after deletion" href="https://code.google.com/p/android/issues/detail?id=13195&amp;can=5&amp;colspec=ID%20Type%20Status%20Owner%20Summary%20Stars" target="_blank"><span class="h3">13195 </span><span class="h3">Certain emails reappear after deletion</span></a></li>
<li><span class="h3"><a title="Bug report 16293 IMAP does not work!" href="https://code.google.com/p/android/issues/detail?id=16293&amp;can=5&amp;colspec=ID%20Type%20Status%20Owner%20Summary%20Stars" target="_blank">16293 IMAP does not work!</a> — a little dramatic <img src='http://ryansechrest.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </span></li>
<li><span class="h3"><a title="Bug report 16484 Email client reload all previously deleted mail" href="https://code.google.com/p/android/issues/detail?id=16484&amp;can=5&amp;colspec=ID%20Type%20Status%20Owner%20Summary%20Stars" target="_blank">16484 Email client reload all previously deleted mail</a><br />
</span></li>
</ol>
<p>From what I gather, most complaints are coming from Samsung users (tablet and phone), but I found a <a title="IMAP Emails Don't Delete To Trash Folder on Motorola Xoom" href="http://forums.androidcentral.com/motorola-xoom/65940-imap-emails-dont-delete-trash-folder.html" target="_blank">few users that reported a similar bug on the Motorola XOOM</a>, which appears to have been resolved. What&#8217;s happening is that Android lost track of the folder that keeps your deleted messages, so when you delete something, it disappears momentarily on the screen, assuming that the command executed successfully, but since Android doesn&#8217;t know where to put that deleted message, it simply keeps it in the inbox. Then when you refresh your inbox to retrieve new messages, it shows back up.</p>
<p>So what can we do about this? There are three workarounds I currently know about.</p>
<h2>1. Move your email message to the trash as apposed to using the delete button</h2>
<p>This is probabaly the least convenient option, as it involves more steps, but it is the quickest to implement. When you&#8217;re looking at your list of emails, press the <span style="text-decoration: underline;">menu</span> key and then the <span style="text-decoration: underline;">move to folder</span> button. Select the messages you want to &#8220;delete&#8221; and click on the <span style="text-decoration: underline;">move to folder</span> button. Then choose your folder, whether it&#8217;s trash (will be stored locally) or something like INBOX.Trash (will be stored in trash on server), and your message(s) will be moved.</p>
<h2>2. Use another email client such as <a title="Learn more about K-9 Mail from Google Project" href="https://code.google.com/p/k9mail/" target="_blank">K-9 Mail</a> (free)</h2>
<p>You basically download an entirely different application and setup all your email accounts on it. The delete command has been confirmed working in K-9 <img src='http://ryansechrest.com/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' />  according to users who have my phone and switched. This application is available for free in the Android market and seems the most recommended.</p>
<h2>3. Root your phone and edit a database file</h2>
<p>This is the only permanent solution that let&#8217;s you keep your stock email application, however, before you can edit this file your phone must be rooted, otherwise you don&#8217;t have access/permissions to do so. If you browse to /data/data/com.android.email/databases/EmailProvider.db on your phone and open this file with a text editor, you can edit your specific email account and reassign that folder. There are more details in a comment on Android&#8217;s project page that discusse another bug report called <a title="Bug report 1811 Email app doesn't handle IMAP folder prefixes properly" href="https://code.google.com/p/android/issues/detail?id=1811#c53" target="_blank">Email app doesn&#8217;t handle IMAP folder prefixes properly</a>, but that same user recommended this fix for being able to delete your messages.</p>
<p>I personally will probably use the first method until I get a firmware update. If the issue then isn&#8217;t fixed, I&#8217;ll consider option #2 or #3.</p>
<p>If someone knows of another solution, I&#8217;d love to hear it! As always, feel free to leave comments below.</p>
<p>-RS</p>
]]></content:encoded>
			<wfw:commentRss>http://ryansechrest.com/2011/12/android-email-application-bug-unable-to-delete-email-messages/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Hybrid form validation: security of server-side (PHP) with efficiency of client-side (jQuery)</title>
		<link>http://ryansechrest.com/2011/12/hybrid-form-validation-security-of-server-side-php-with-efficiency-of-client-side-jquery/</link>
		<comments>http://ryansechrest.com/2011/12/hybrid-form-validation-security-of-server-side-php-with-efficiency-of-client-side-jquery/#comments</comments>
		<pubDate>Sun, 11 Dec 2011 21:57:34 +0000</pubDate>
		<dc:creator>Ryan</dc:creator>
				<category><![CDATA[Code]]></category>
		<category><![CDATA[CSS]]></category>
		<category><![CDATA[jQuery]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[XHTML]]></category>
		<category><![CDATA[ajax]]></category>
		<category><![CDATA[client-side]]></category>
		<category><![CDATA[form]]></category>
		<category><![CDATA[server-side]]></category>
		<category><![CDATA[user-friendly]]></category>
		<category><![CDATA[validation]]></category>

		<guid isPermaLink="false">http://ryansechrest.com/?p=180</guid>
		<description><![CDATA[Preface I&#8217;ve built a lot of forms in my day, and to be honest, it&#8217;s not one of my favorite things to do. The designing and building aspect is fun, but the validation and error reporting, ehh. We all know &#8230; <a href="http://ryansechrest.com/2011/12/hybrid-form-validation-security-of-server-side-php-with-efficiency-of-client-side-jquery/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<h2>Preface</h2>
<p>I&#8217;ve built a lot of forms in my day, and to be honest, it&#8217;s not one of my favorite things to do. The designing and building aspect is fun, but the validation and error reporting, <em>ehh</em>. We all know that server-side validation is a must, and technically speaking, client-side validation optional, but if you love your users, you&#8217;ll do it anyway. The challenge then for you, as the web developer, is to vigorously ensure that the client-side (<a title="Learn more about jQuery" href="http://jquery.com/" target="_blank">jQuery</a>) and server-side (<a title="Learn more about PHP" href="http://www.php.net/" target="_blank">PHP</a>) validation are identical, so you don&#8217;t have discrepancies that confuse your users. The reason client-side validation makes users happy, is because the errors pop up right away and the page doesn&#8217;t need to be reloaded.</p>
<p>What if you could trade the pain of writing a client-side validation script with making  server-side validation instantaneous? Yes, <a title="Learn more about AJAX from Wikipedia" href="https://en.wikipedia.org/wiki/Ajax_%28programming%29" target="_blank">AJAX</a> comes to mind, however, the one thing people tend to do with that is display all the errors grouped together, because the AJAX response either updates or adds a div below or above the form, making the user have to figure out which error belongs to which field.</p>
<h2>Project</h2>
<p>The goal is to validate forms in the most efficient and user-friendly way, without having to compromise speed or security.</p>
<h2>Requirements</h2>
<ul>
<li>Completely omit client-side validation</li>
<li>Display errors instantaneously next to corresponding fields</li>
<li>Prevent the page from being refreshed</li>
</ul>
<h2>Solution</h2>
<p>The user fills out a form and it gets submitted via jQuery. If the submission takes just a bit longer, a processing message will appear. A separate processing script will validate each field and upon error, store that error in an array using the field&#8217;s label as the array item&#8217;s key and the error as the array item&#8217;s value. At the end of the validation, it will send the form back by calling the form&#8217;s function — a <a title="Learn more about user-defined PHP functions from PHP.net" href="http://php.net/manual/en/language.functions.php" target="_blank">user-defined PHP function</a> — with the error array as an argument. jQuery then replaces the existing form on the page with a new form that displays the errors underneath each field. jQuery&#8217;s on event handler then ensures that the replaced form is re-submittable.</p>
<h2>Implementation</h2>
<p>Below is the user-defined <strong>PHP</strong> function that creates the HTML form:</p>

<div class="bwp-syntax-block clearfix">
<div class="bwp-syntax-toolbar" style="right: 15px;" ><div class="bwp-syntax-control"><a href="javascript:;" class="bwp-syntax-source-switch" title="View Source Code"></a></div></div>
<div class="bwp-syntax-wrapper clearfix bwp-syntax-simple"style=" height: 436.8px;"><table class="php"><tbody><tr class="li1"><td class="ln"><pre class="de1">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
</pre></td><td class="de1"><pre class="de1"><span class="co1">// Returns a login form</span>
<span class="co1">// @param (array) errors [optional]</span>
<span class="co1">// @return (string) login form</span>
<span class="kw2">function</span> getLoginForm<span class="br0">&#40;</span><span class="re0">$errors</span> <span class="sy0">=</span> <span class="kw4">false</span><span class="br0">&#41;</span> <span class="br0">&#123;</span>
&nbsp; <span class="re0">$output</span> <span class="sy0">.=</span> <span class="st_h">'&lt;form action=&quot;#&quot; name=&quot;login&quot; method=&quot;post&quot;&gt;'</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="re0">$output</span> <span class="sy0">.=</span> <span class="st_h">'&lt;h2&gt;Sign in to '</span> <span class="sy0">.</span> APPNAME <span class="sy0">.</span> <span class="st_h">'&lt;/h2&gt;'</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="re0">$output</span> <span class="sy0">.=</span> <span class="st_h">'&lt;div class=&quot;field&quot;&gt;'</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; <span class="re0">$output</span> <span class="sy0">.=</span> <span class="st_h">'&lt;label for=&quot;username&quot;&gt;Username&lt;/label&gt;'</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; <span class="re0">$output</span> <span class="sy0">.=</span> <span class="st_h">'&lt;input type=&quot;text&quot; id=&quot;username&quot; name=&quot;username&quot; autofocus=&quot;autofocus&quot;'</span> <span class="sy0">.</span> getPostValue<span class="br0">&#40;</span><span class="st_h">'username'</span><span class="br0">&#41;</span> &nbsp;<span class="sy0">.</span> <span class="st_h">' /&gt;'</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; <span class="kw1">if</span><span class="br0">&#40;</span><span class="kw3">isset</span><span class="br0">&#40;</span><span class="re0">$errors</span><span class="br0">&#91;</span><span class="st_h">'username'</span><span class="br0">&#93;</span><span class="br0">&#41;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="re0">$output</span> <span class="sy0">.=</span> <span class="st_h">'&lt;div class=&quot;help&quot;&gt;'</span> <span class="sy0">.</span> <span class="re0">$errors</span><span class="br0">&#91;</span><span class="st_h">'username'</span><span class="br0">&#93;</span> <span class="sy0">.</span> <span class="st_h">'&lt;/div&gt;'</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp; &nbsp; <span class="re0">$output</span> <span class="sy0">.=</span> <span class="st_h">'&lt;/div&gt;'</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="re0">$output</span> <span class="sy0">.=</span> <span class="st_h">'&lt;div class=&quot;field&quot;&gt;'</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; <span class="re0">$output</span> <span class="sy0">.=</span> <span class="st_h">'&lt;label for=&quot;password&quot;&gt;Password&lt;/label&gt;'</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; <span class="re0">$output</span> <span class="sy0">.=</span> <span class="st_h">'&lt;input type=&quot;password&quot; id=&quot;password&quot; name=&quot;password&quot;'</span> <span class="sy0">.</span> getPostValue<span class="br0">&#40;</span><span class="st_h">'password'</span><span class="br0">&#41;</span> &nbsp;<span class="sy0">.</span> <span class="st_h">' /&gt;'</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; <span class="kw1">if</span><span class="br0">&#40;</span><span class="kw3">isset</span><span class="br0">&#40;</span><span class="re0">$errors</span><span class="br0">&#91;</span><span class="st_h">'passsword'</span><span class="br0">&#93;</span><span class="br0">&#41;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="re0">$output</span> <span class="sy0">.=</span> <span class="st_h">'&lt;div class=&quot;help&quot;&gt;'</span> <span class="sy0">.</span> <span class="re0">$errors</span><span class="br0">&#91;</span><span class="st_h">'username'</span><span class="br0">&#93;</span> <span class="sy0">.</span> <span class="st_h">'&lt;/div&gt;'</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp; &nbsp; <span class="re0">$output</span> <span class="sy0">.=</span> <span class="st_h">'&lt;/div&gt;'</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="re0">$output</span> <span class="sy0">.=</span> <span class="st_h">'&lt;div class=&quot;message&quot;&gt;&lt;/div&gt;'</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="re0">$output</span> <span class="sy0">.=</span> <span class="st_h">'&lt;div class=&quot;button&quot;&gt;'</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; <span class="re0">$output</span> <span class="sy0">.=</span> <span class="st_h">'&lt;button type=&quot;button&quot; name=&quot;commit&quot; disabled=&quot;disabled&quot;&gt;Login&lt;/button&gt;'</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="re0">$output</span> <span class="sy0">.=</span> <span class="st_h">'&lt;/div&gt;'</span><span class="sy0">;</span>
&nbsp; <span class="re0">$output</span> <span class="sy0">.=</span> <span class="st_h">'&lt;/form&gt;'</span><span class="sy0">;</span>
&nbsp; <span class="kw1">return</span> <span class="re0">$output</span><span class="sy0">;</span>
<span class="br0">&#125;</span></pre></td></tr></tbody></table></div>
<div class="bwp-syntax-source"><pre class="no-parse">// Returns a login form
// @param (array) errors [optional]
// @return (string) login form
function getLoginForm($errors = false) {
	$output .= '&lt;form action="#" name="login" method="post"&gt;';
		$output .= '&lt;h2&gt;Sign in to ' . APPNAME . '&lt;/h2&gt;';
		$output .= '&lt;div class="field"&gt;';
			$output .= '&lt;label for="username"&gt;Username&lt;/label&gt;';
			$output .= '&lt;input type="text" id="username" name="username" autofocus="autofocus"' . getPostValue('username')  . ' /&gt;';
			if(isset($errors['username'])) {
				$output .= '&lt;div class="help"&gt;' . $errors['username'] . '&lt;/div&gt;';
			}
		$output .= '&lt;/div&gt;';
		$output .= '&lt;div class="field"&gt;';
			$output .= '&lt;label for="password"&gt;Password&lt;/label&gt;';
			$output .= '&lt;input type="password" id="password" name="password"' . getPostValue('password')  . ' /&gt;';
			if(isset($errors['passsword'])) {
				$output .= '&lt;div class="help"&gt;' . $errors['username'] . '&lt;/div&gt;';
			}
		$output .= '&lt;/div&gt;';
		$output .= '&lt;div class="message"&gt;&lt;/div&gt;';
		$output .= '&lt;div class="button"&gt;';
			$output .= '&lt;button type="button" name="commit" disabled="disabled"&gt;Login&lt;/button&gt;';
		$output .= '&lt;/div&gt;';
	$output .= '&lt;/form&gt;';
	return $output;
}</pre></div></div>

<ul>
<li>On <span style="color: #ff6600;">line 4</span> you see the optional argument. The variable is set to false so that PHP doesn&#8217;t complain when the function is called without a parameter.</li>
<li>On <span style="color: #ff6600;">line 6</span> I&#8217;m using a <a title="Learn more about named constants from PHP.net" href="http://php.net/manual/en/function.define.php" target="_blank">named constant</a> to display what the user is logging into. You could replace that with static text.</li>
<li>On <span style="color: #ff6600;">line 9</span> I have another custom function called getPostValue() that basically escapes the user&#8217;s input before displaying it inside the field.</li>
<li>On <span style="color: #ff6600;">line 10</span> we&#8217;re checking to see whether an array item with a key, that matches the field&#8217;s label, exists. If it does, we know to display an error, if not, that whole help div container is omitted.</li>
</ul>
<p>Here is how the rendered form looks like in <strong>HTML</strong>:</p>

<div class="bwp-syntax-block clearfix">
<div class="bwp-syntax-toolbar"><div class="bwp-syntax-control"><a href="javascript:;" class="bwp-syntax-source-switch" title="View Source Code"></a></div></div>
<div class="bwp-syntax-wrapper clearfix bwp-syntax-simple"><table class="html4strict"><tbody><tr class="li1"><td class="ln"><pre class="de1">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
</pre></td><td class="de1"><pre class="de1"><span class="sc2">&lt;<span class="kw2">div</span> <span class="kw3">class</span><span class="sy0">=</span><span class="st0">&quot;init&quot;</span>&gt;</span>
&nbsp; <span class="sc2">&lt;<span class="kw2">form</span> <span class="kw3">action</span><span class="sy0">=</span><span class="st0">&quot;#&quot;</span> <span class="kw3">name</span><span class="sy0">=</span><span class="st0">&quot;login&quot;</span> <span class="kw3">method</span><span class="sy0">=</span><span class="st0">&quot;post&quot;</span>&gt;</span>
&nbsp; &nbsp; <span class="sc2">&lt;<span class="kw2">h2</span>&gt;</span>Sign in to SME<span class="sc2">&lt;<span class="sy0">/</span><span class="kw2">h2</span>&gt;</span>
&nbsp; &nbsp; <span class="sc2">&lt;<span class="kw2">div</span> <span class="kw3">class</span><span class="sy0">=</span><span class="st0">&quot;field&quot;</span>&gt;</span>
&nbsp; &nbsp; &nbsp; <span class="sc2">&lt;<span class="kw2">label</span> <span class="kw3">for</span><span class="sy0">=</span><span class="st0">&quot;username&quot;</span>&gt;</span>Username<span class="sc2">&lt;<span class="sy0">/</span><span class="kw2">label</span>&gt;</span>
&nbsp; &nbsp; &nbsp; <span class="sc2">&lt;<span class="kw2">input</span> <span class="kw3">type</span><span class="sy0">=</span><span class="st0">&quot;text&quot;</span> <span class="kw3">id</span><span class="sy0">=</span><span class="st0">&quot;username&quot;</span> <span class="kw3">name</span><span class="sy0">=</span><span class="st0">&quot;username&quot;</span> autofocus<span class="sy0">=</span><span class="st0">&quot;autofocus&quot;</span> <span class="sy0">/</span>&gt;</span>
&nbsp; &nbsp; <span class="sc2">&lt;<span class="sy0">/</span><span class="kw2">div</span>&gt;</span>
&nbsp; &nbsp; <span class="sc2">&lt;<span class="kw2">div</span> <span class="kw3">class</span><span class="sy0">=</span><span class="st0">&quot;field&quot;</span>&gt;</span>
&nbsp; &nbsp; &nbsp; <span class="sc2">&lt;<span class="kw2">label</span> <span class="kw3">for</span><span class="sy0">=</span><span class="st0">&quot;password&quot;</span>&gt;</span>Password<span class="sc2">&lt;<span class="sy0">/</span><span class="kw2">label</span>&gt;</span>
&nbsp; &nbsp; &nbsp; <span class="sc2">&lt;<span class="kw2">input</span> <span class="kw3">type</span><span class="sy0">=</span><span class="st0">&quot;password&quot;</span> <span class="kw3">id</span><span class="sy0">=</span><span class="st0">&quot;password&quot;</span> <span class="kw3">name</span><span class="sy0">=</span><span class="st0">&quot;password&quot;</span> <span class="sy0">/</span>&gt;</span>
&nbsp; &nbsp; <span class="sc2">&lt;<span class="sy0">/</span><span class="kw2">div</span>&gt;</span>
&nbsp; &nbsp; <span class="sc2">&lt;<span class="kw2">div</span> <span class="kw3">class</span><span class="sy0">=</span><span class="st0">&quot;message&quot;</span>&gt;&lt;<span class="sy0">/</span><span class="kw2">div</span>&gt;</span>
&nbsp; &nbsp; <span class="sc2">&lt;<span class="kw2">div</span> <span class="kw3">class</span><span class="sy0">=</span><span class="st0">&quot;button&quot;</span>&gt;</span>
&nbsp; &nbsp; &nbsp; <span class="sc2">&lt;<span class="kw2">button</span> <span class="kw3">type</span><span class="sy0">=</span><span class="st0">&quot;button&quot;</span> <span class="kw3">name</span><span class="sy0">=</span><span class="st0">&quot;commit&quot;</span> <span class="kw3">disabled</span><span class="sy0">=</span><span class="st0">&quot;disabled&quot;</span>&gt;</span>Login<span class="sc2">&lt;<span class="sy0">/</span><span class="kw2">button</span>&gt;</span>
&nbsp; &nbsp; <span class="sc2">&lt;<span class="sy0">/</span><span class="kw2">div</span>&gt;</span>
&nbsp; <span class="sc2">&lt;<span class="sy0">/</span><span class="kw2">form</span>&gt;</span>
<span class="sc2">&lt;<span class="sy0">/</span><span class="kw2">div</span>&gt;</span></pre></td></tr></tbody></table></div>
<div class="bwp-syntax-source"><pre class="no-parse">&lt;div class="init"&gt;
	&lt;form action="#" name="login" method="post"&gt;
		&lt;h2&gt;Sign in to SME&lt;/h2&gt;
		&lt;div class="field"&gt;
			&lt;label for="username"&gt;Username&lt;/label&gt;
			&lt;input type="text" id="username" name="username" autofocus="autofocus" /&gt;
		&lt;/div&gt;
		&lt;div class="field"&gt;
			&lt;label for="password"&gt;Password&lt;/label&gt;
			&lt;input type="password" id="password" name="password" /&gt;
		&lt;/div&gt;
		&lt;div class="message"&gt;&lt;/div&gt;
		&lt;div class="button"&gt;
			&lt;button type="button" name="commit" disabled="disabled"&gt;Login&lt;/button&gt;
		&lt;/div&gt;
	&lt;/form&gt;
&lt;/div&gt;</pre></div></div>

<ul>
<li>On <span style="color: #ff6600;">line 1</span> we need to wrap the form in a div, so we can later monitor it with jQuery. What happens is that jQuery will replace the entire form with one that shows the errors. Because that new form is a new object to the page, jQuery doesn&#8217;t know about it. It needs a fixed element on the page, such as the init div, whose contents it can monitor.</li>
<li>On <span style="color: #ff6600;">line 2</span> you&#8217;ll notice that the action attribute is empty. This particular project requires users to have JavaScript turned on, but if you expect users without JavaScript, it&#8217;s a good idea to enter the path of the processor,.</li>
<li>On <span style="color: #ff6600;">line 12</span> we will show a message to the user when the button gets clicked, so they know the form is processing.</li>
<li>On <span style="color: #ff6600;">line 14</span> you&#8217;ll notice that I used the button tag to render a button as apposed to the classic &lt;input type=&#8221;submit&#8221;&gt;. I do that simply so I can style my text fields without having to worry that it will affect my buttons. My button is by default disabled and I then enable it with JavaScript, that way if JavaScript is turned off, the form can&#8217;t be submitted. Lastly, my button is of type=&#8221;button&#8221;, which by default doesn&#8217;t do anything (I assign an event handler with jQuery later). You&#8217;d make it of type=&#8221;submit&#8221; if you wanted that button to work without JavaScript.</li>
</ul>
<p>Below is the <strong>jQuery</strong> that is in charge of submitting the form:</p>

<div class="bwp-syntax-block clearfix">
<div class="bwp-syntax-toolbar" style="right: 15px;" ><div class="bwp-syntax-control"><a href="javascript:;" class="bwp-syntax-source-switch" title="View Source Code"></a></div></div>
<div class="bwp-syntax-wrapper clearfix bwp-syntax-simple"style=" height: 436.8px;"><table class="javascript"><tbody><tr class="li1"><td class="ln"><pre class="de1">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
</pre></td><td class="de1"><pre class="de1">$<span class="br0">&#40;</span>document<span class="br0">&#41;</span>.<span class="me1">ready</span><span class="br0">&#40;</span><span class="kw2">function</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#123;</span>
&nbsp;
&nbsp; initBinding<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; <span class="co1">// Send any form to its specific processor</span>
&nbsp; $<span class="br0">&#40;</span><span class="st0">'body'</span><span class="br0">&#41;</span>.<span class="me1">on</span><span class="br0">&#40;</span><span class="st0">'submit'</span><span class="sy0">,</span> <span class="st0">'form'</span><span class="sy0">,</span> <span class="kw2">function</span><span class="br0">&#40;</span>e<span class="br0">&#41;</span><span class="br0">&#123;</span>
&nbsp; &nbsp; <span class="kw2">var</span> form <span class="sy0">=</span> $<span class="br0">&#40;</span><span class="kw1">this</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; form.<span class="me1">find</span><span class="br0">&#40;</span><span class="st0">'button[name=commit]'</span><span class="br0">&#41;</span>.<span class="me1">attr</span><span class="br0">&#40;</span><span class="st0">'disabled'</span><span class="sy0">,</span> <span class="st0">'disabled'</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; form.<span class="me1">find</span><span class="br0">&#40;</span><span class="st0">'.message'</span><span class="br0">&#41;</span>.<span class="me1">delay</span><span class="br0">&#40;</span><span class="nu0">100</span><span class="br0">&#41;</span>.<span class="me1">queue</span><span class="br0">&#40;</span><span class="kw2">function</span><span class="br0">&#40;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; $<span class="br0">&#40;</span><span class="kw1">this</span><span class="br0">&#41;</span>.<span class="me1">html</span><span class="br0">&#40;</span><span class="st0">'&lt;div class=&quot;pending&quot;&gt;Sending your request... please wait...&lt;/div&gt;'</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; $.<span class="me1">post</span><span class="br0">&#40;</span><span class="st0">'process.php?p='</span> <span class="sy0">+</span> form.<span class="me1">attr</span><span class="br0">&#40;</span><span class="st0">'name'</span><span class="br0">&#41;</span><span class="sy0">,</span> form.<span class="me1">serialize</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">,</span> <span class="kw2">function</span><span class="br0">&#40;</span>response<span class="br0">&#41;</span> <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; form.<span class="me1">parent</span><span class="br0">&#40;</span><span class="st0">'div'</span><span class="br0">&#41;</span>.<span class="me1">html</span><span class="br0">&#40;</span>response<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; initBinding<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; e.<span class="me1">preventDefault</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; <span class="br0">&#125;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; <span class="kw2">function</span> initBinding<span class="br0">&#40;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span>
&nbsp; &nbsp; <span class="co1">// Enable the form's submit button and assign event handler</span>
&nbsp; &nbsp; $<span class="br0">&#40;</span><span class="st0">'button[name=commit]'</span><span class="br0">&#41;</span>.<span class="me1">removeAttr</span><span class="br0">&#40;</span><span class="st0">'disabled'</span><span class="br0">&#41;</span>.<span class="me1">click</span><span class="br0">&#40;</span><span class="kw2">function</span><span class="br0">&#40;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; $<span class="br0">&#40;</span><span class="kw1">this</span><span class="br0">&#41;</span>.<span class="me1">trigger</span><span class="br0">&#40;</span><span class="st0">'submit'</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; <span class="br0">&#125;</span>
&nbsp;
<span class="br0">&#125;</span><span class="br0">&#41;</span><span class="sy0">;</span></pre></td></tr></tbody></table></div>
<div class="bwp-syntax-source"><pre class="no-parse">$(document).ready(function(){

	initBinding();

	// Send any form to its specific processor
	$('body').on('submit', 'form', function(e){
		var form = $(this);
		form.find('button[name=commit]').attr('disabled', 'disabled');
		form.find('.message').delay(100).queue(function() {
			$(this).html('&lt;div class="pending"&gt;Sending your request... please wait...&lt;/div&gt;');
		});
		$.post('process.php?p=' + form.attr('name'), form.serialize(), function(response) {
			form.parent('div').html(response);
			initBinding();
		});
		e.preventDefault();
	});

	function initBinding() {
		// Enable the form's submit button and assign event handler
		$('button[name=commit]').removeAttr('disabled').click(function() {
			$(this).trigger('submit');
		});
	}

});</pre></div></div>

<ul>
<li>On <span style="color: #ff6600;">line 3</span> I&#8217;m calling a function that enables my disabled submit button and assigns a click event to it, so it can submit the form, since my button doesn&#8217;t natively do that.</li>
<li>On <span style="color: #ff6600;">line 6</span> we&#8217;re using jQuery&#8217;s <a title="Learn more about jQuery's on event handler from jQuery.com" href="http://api.jquery.com/on/" target="_blank">on event handler</a>, which basically monitors the HTML body and looks for changes in a form element. This is important so that the form can be resubmitted. When the form gets replaced, it&#8217;s an unknown object on the page, however, since jQuery is monitoring it, it will convert the newly replaced form to a submittable form.</li>
<li>On <span style="color: #ff6600;">line 8</span> I&#8217;m disabling the button, so while the form is processing, it can&#8217;t be submitted a second time.</li>
<li>On <span style="color: #ff6600;">line 9</span> you&#8217;ll notice that we delay the &#8220;processing&#8221; message slightly, because if it submits right away, there&#8217;s no reason to flash it on the screen, but if it takes a bit longer, the user should know that something is happening.</li>
<li>On <span style="color: #ff6600;">line 12</span> is where we actually post the form. I&#8217;m sending it to process.php, which contains a <a title="Learn more about the switch control structure from PHP.net" href="http://php.net/manual/en/control-structures.switch.php" target="_blank">switch control structure</a> that receives the form attribute&#8217;s name, so that the processor knows which fields to expect and validate.</li>
<li>On <span style="color: #ff6600;">line 14</span> I&#8217;m calling initBinding() again, so that the newly replaced form&#8217;s submit button will be re-enabled and can submit again.</li>
</ul>
<h2>Conclusion</h2>
<p>You get an easily maintainable and secure form for which you don&#8217;t have to write any client-side validation. The form is submitted via jQuery, which doesn&#8217;t require the page to be reloaded, and the validation appears almost instantaneous to the user, just as if you had used client-side validation.</p>
<p>If you have any questions or suggestions, please feel free to leave comments below.</p>
<p>-RS</p>
]]></content:encoded>
			<wfw:commentRss>http://ryansechrest.com/2011/12/hybrid-form-validation-security-of-server-side-php-with-efficiency-of-client-side-jquery/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

