<?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>Open Development</title>
	<atom:link href="http://blogs.tankersleywebsolutions.com/feed/" rel="self" type="application/rss+xml" />
	<link>http://blogs.tankersleywebsolutions.com</link>
	<description>An Open Discussion on the Web and Programming</description>
	<lastBuildDate>Sun, 28 Feb 2010 18:17:23 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.8.4</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Multiple Config Files with Zend_Application</title>
		<link>http://blogs.tankersleywebsolutions.com/2010/02/28/multiple-config-files-with-zend_application/</link>
		<comments>http://blogs.tankersleywebsolutions.com/2010/02/28/multiple-config-files-with-zend_application/#comments</comments>
		<pubDate>Sun, 28 Feb 2010 18:17:23 +0000</pubDate>
		<dc:creator>chris</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[Tutorials]]></category>
		<category><![CDATA[Coding]]></category>
		<category><![CDATA[Zend Framework]]></category>

		<guid isPermaLink="false">http://blogs.tankersleywebsolutions.com/?p=263</guid>
		<description><![CDATA[With the recent release of Manuscript, one of the things I added to the application was an installer. The installer is pretty basic and just asks for some database information that gets written to the config files.
This posed a problem. Zend_Config_Writer will only write to a file, not update it. I would need to read [...]]]></description>
			<content:encoded><![CDATA[<p>With the recent release of <a href="http://code.google.com/p/manuscript">Manuscript</a>, one of the things I added to the application was an installer. The installer is pretty basic and just asks for some database information that gets written to the config files.</p>
<p>This posed a problem.<a href="http://framework.zend.com/manual/en/zend.config.writer.html"> Zend_Config_Writer</a> will only write to a file, not update it. I would need to read in all the sections of the application.ini file (production, testing, development) and take into account any sections added by users and dependencies, remove the old file and write the new one. That seemed very heavy handed and dangerous. </p>
<p><a href="http://framework.zend.com/manual/en/zend.config.html">Zend_Config</a> has a merge() function, so the idea came to me to use two config files. Keep the application.ini file for system values that are &#8216;global&#8217; across installations, and then added a local.ini for things like DB settings. Zend_Config_Writer would just write local.ini settings to the global space and everything would be great. Merge the local settings into the application settings and your done!</p>
<p>A problem surfaced. Manuscript is built using <a href="http://framework.zend.com/manual/en/zend.application.html">Zend_Application</a>. Zend_Application takes care of all the bootstrapping, reading the config files, and setting up all the dirty stuff for me. It also only takes the path of single config file. I have two config files. Crap.</p>
<p>Luckily Zend_Application doesn&#8217;t automatically bootstrap itself, but it does load the configuration immediately. What I ended up doing was this:</p>
<p  style="text-align: left">

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
</pre></td><td class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000088;">$application</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> Zend_Application<span style="color: #009900;">&#40;</span>
    APPLICATION_ENV<span style="color: #339933;">,</span>
    APPLICATION_PATH <span style="color: #339933;">.</span> <span style="color: #0000ff;">'/configs/application.ini'</span>
<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #000088;">$localConfigFile</span> <span style="color: #339933;">=</span> APPLICATION_PATH<span style="color: #339933;">.</span><span style="color: #0000ff;">'/configs/local.ini'</span><span style="color: #339933;">;</span>
<span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span><span style="color: #990000;">is_file</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$localConfigFile</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
    <span style="color: #000088;">$config</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> Zend_Config<span style="color: #009900;">&#40;</span><span style="color: #000088;">$application</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getOptions</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span> <span style="color: #009900; font-weight: bold;">true</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #000088;">$local</span>  <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> Zend_Config_Ini<span style="color: #009900;">&#40;</span><span style="color: #000088;">$localConfigFile</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #000088;">$config</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">merge</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$local</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #000088;">$application</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">setOptions</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$config</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">toArray</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #000088;">$application</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">bootstrap</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>
            <span style="color: #339933;">-&gt;</span><span style="color: #004000;">run</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></td></tr></table></div>

</p>
<p>You initialize Zend_Application like normal and call the default application.ini. Zend_Application makes that config file available as an array, so I pull the loaded config back out and pass it into a new array-based Zend_Config ($config in the above). I create a second config ($local) with Zend_Config_Ini. </p>
<p>Using merge(), I merge the $local file into the $config file. This gets me a proper representation of what I wanted. I push this config back into Zend_Application and then call the bootstrap. The bootstrap is none the wiser that it actually is using two config files and my database gets bootstrapped properly!</p>
<p>It is not as clean as I want it to be but it gets the job done and users can override or add their own config information to local.ini and not worry about editing the supplied config file in the release.</p>
]]></content:encoded>
			<wfw:commentRss>http://blogs.tankersleywebsolutions.com/2010/02/28/multiple-config-files-with-zend_application/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Uploading Files using Zend Framework</title>
		<link>http://blogs.tankersleywebsolutions.com/2010/01/07/uploading-files-using-zend-framework/</link>
		<comments>http://blogs.tankersleywebsolutions.com/2010/01/07/uploading-files-using-zend-framework/#comments</comments>
		<pubDate>Fri, 08 Jan 2010 01:54:00 +0000</pubDate>
		<dc:creator>chris</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[Tutorials]]></category>
		<category><![CDATA[Coding]]></category>
		<category><![CDATA[Tips]]></category>
		<category><![CDATA[Tutorial]]></category>
		<category><![CDATA[Zend Framework]]></category>

		<guid isPermaLink="false">http://blogs.tankersleywebsolutions.com/?p=256</guid>
		<description><![CDATA[Uploading files in PHP is easy, if not tedious. A lot of the projects that I work on involve some type of upload of files and after a while it gets old. Doing all the checks to make sure the file is there, generating forms, etc &#8230; there must be an easier way, right?
Well, there [...]]]></description>
			<content:encoded><![CDATA[<p>Uploading files in PHP is easy, if not tedious. A lot of the projects that I work on involve some type of upload of files and after a while it gets old. Doing all the checks to make sure the file is there, generating forms, etc &#8230; there must be an easier way, right?</p>
<p>Well, there is. The <a href="http://framework.zend.com" target="_blank">Zend Framework</a> introduced a few classes to help facilitate uploading and working with files after they make it to the server. Taking advantage of <a href="http://framework.zend.com/manual/en/zend.form.standardElements.html#zend.form.standardElements.file" target="_blank">Zend_Form_Element_File</a> and the <a href="http://framework.zend.com/manual/en/zend.file.html" target="_self">Zend_File_Transfer_Adapter_Http</a> makes it dead simple to upload a file.</p>
<p><span id="more-256"></span></p>
<h2>Generating a Form</h2>
<p>The first step is to generate a form. I use <a href="http://framework.zend.com/manual/en/zend.form.html" target="_blank">Zend_Form</a> more and more for this as it takes away having to do the markup for forms as well as provides an easy way to mark up the forms. Let&#8217;s make a simple upload form:</p>
<p>[cce_php]<br />
class Form_MyForm extends Zend_Form {<br />
public function init() {<br />
$file = new Zend_Form_Element_File(&#8217;file&#8217;);<br />
$file->setLabel(&#8217;File to Upload:&#8217;)-&gt;setRequired(true);</p>
<p>$submit = new Zend_Form_Element_Submit(&#8217;submit&#8217;);<br />
$submit->setLabel(&#8217;Upload File&#8217;);<br />
$this->assignElements(array($file, $submit));<br />
}<br />
}<br />
[/cce_php]</p>
<p>Zend_Form 1.9.6 takes care of making sure that the form itself is set to to the proper encoding type for you and making sure that a MAX_FILESIZE field is set up. Less work you have to do! Now you just display that form in your view.</p>
<h2>Getting the File</h2>
<p>Now that we&#8217;re allowing the user to upload the file, how do we get it? You can go back to using the $_FILES superglobal and the upload functions but there is an easier way. Let&#8217;s take a look.</p>
<p>[cce_php]<br />
// Check for Post and Validate your form before this</p>
<p>// Define a transport and set the destination on the server<br />
$upload = new Zend_File_Transfer_Adapter_Http();<br />
$upload->setDestination(APPLICATION_PATH.&#8217;/../data/&#8217;);</p>
<p>try {<br />
// This takes care of the moving and making sure the file is there<br />
$upload->receive();<br />
// Dump out all the file info<br />
Zend_Debug::dump($upload->getFileInfo());<br />
} catch (Zend_File_Transfer_Exception $e) {<br />
echo $e->message();<br />
}<br />
[/cce_php]</p>
<p>So with 8 lines of code we have our error checking and getting the file moved into the proper place. It does all the is_uploaded_file, move_uploaded_file, making sure it gets there, and renaming the file. That&#8217;s it!</p>
<h3>But wait, I don&#8217;t want the filename to be whatever the original filename was!</h3>
<p>You&#8217;re covered. <a href="http://framework.zend.com/manual/en/zend.file.transfer.filters.html#zend.file.transfer.filters.rename">Zend_Filter_File_Rename</a> allows you to rename a file however you want when you receive the file. Let&#8217;s say you allow the user to upload a new avatar picture for a Forum, and that file is always called &#8216;$userId.jpg&#8217;.</p>
<p>[cce_php]<br />
$upload = new Zend_File_Transfer_Adapter_Http();<br />
$upload->addFilter(&#8217;Rename&#8217;, APPLICATION_PATH.&#8217;/../public/images/avatars/&#8217;.$userId.&#8217;.jpg&#8217;);<br />
[/cce_php]</p>
<p>That&#8217;s it. When the file is received (and that is the important part which I&#8217;ll show in a minute) it will be renamed and put in the appropriate folder. Notice I didn&#8217;t set a destination &#8211; when using the Rename filter, the destination is part of the filter.</p>
<h2>Caveats</h2>
<h3>Receiving a file, and Zend_Form::getValues()</h3>
<p>Always make sure to receive your file with the receive() method <em>before</em> calling the getValues() method on your form. getValues() will internally try and shuffle your file around since Zend_Form is aware of the file upload and receive() won&#8217;t work. It is an easy but frustrating mistake to make.</p>
<h3>Renaming and Receiving a file</h3>
<p>Try the following:</p>
<p>[cce_php]<br />
$upload = new Zend_File_Transfer_Adapter_Http();<br />
$upload->addFilter(&#8217;Rename&#8217;, APPLICATION_PATH.&#8217;/../public/images/avatars/&#8217;.$userId.&#8217;.jpg&#8217;);<br />
Zend_Debug::dump($upload->getFileInfo());<br />
$upload->receive();<br />
Zend_Debug::dump($upload->getFileInfo());<br />
[/cce_php]</p>
<p>You&#8217;ll notice that the name of the file doesn&#8217;t get rewritten until after the receive. This is because the file is already on the server by the time your code runs, the Transport just makes it easier to work with. It is important to remember this if you need the original filename but don&#8217;t want that to be the name on the local filesystem. Once the Rename filter is run the original filename is lost.</p>
<p>For example, in one internal project for myself I upload the files and hash the name on the filesystem, but in the database I need to have the original filename when the user downloads the file. In that case you can call all the Zend_File_Transfer_Adapter_Http() methods before the rename, receive the file, and then work with the file after that.</p>
<h2>Going Futher</h2>
<p>The <a href="http://framework.zend.com/manual/en/zend.file.html">manual for Zend_File</a> has more filters and examples for the uploaded files. You can even have your form support multiple file upload elements with minor alterations to the examples above. There are validators specifically for files to make the file uploads safer (not foolproof, but a bit safter)</p>
<p>Take advantage of Zend Framework&#8217;s tight integration for forms and file uploads and make your life easier.</p>
]]></content:encoded>
			<wfw:commentRss>http://blogs.tankersleywebsolutions.com/2010/01/07/uploading-files-using-zend-framework/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Don&#8217;t Trust Your Users</title>
		<link>http://blogs.tankersleywebsolutions.com/2009/11/03/dont-trust-your-users/</link>
		<comments>http://blogs.tankersleywebsolutions.com/2009/11/03/dont-trust-your-users/#comments</comments>
		<pubDate>Wed, 04 Nov 2009 03:02:54 +0000</pubDate>
		<dc:creator>chris</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[Software]]></category>
		<category><![CDATA[Tutorials]]></category>
		<category><![CDATA[filtering]]></category>
		<category><![CDATA[gigo]]></category>
		<category><![CDATA[Security]]></category>
		<category><![CDATA[users]]></category>
		<category><![CDATA[Zend Framework]]></category>

		<guid isPermaLink="false">http://blogs.tankersleywebsolutions.com/?p=242</guid>
		<description><![CDATA[My programming teacher was full of useful acronyms when it came to teaching us things. KISS (Keep it Simple Stupid), DRY (Don’t Repeat Yourself), IPO (Input-Process-Output), and probably one of the most useful, if understated:
GIGO = Garbage In, Garbage Out
Those four letters are probably some of the most ignored four (OK, three) letters in programming. [...]]]></description>
			<content:encoded><![CDATA[<p>My programming teacher was full of useful acronyms when it came to teaching us things. KISS (Keep it Simple Stupid), DRY (Don’t Repeat Yourself), IPO (Input-Process-Output), and probably one of the most useful, if understated:</p>
<p><strong>GIGO = Garbage In, Garbage Out</strong></p>
<p><span style="color: #2e2e2e">Those four letters are probably some of the most ignored four (OK, three) letters in programming. Most programmers assume wrongly that their users are not out to get them and destroy precious data, but they are. Fortunately most users don’t know that they are trying to destroy the precious balance that most web apps have, and unfortunately most web apps don’t care. Programmers then have to worry about the rest of the users that are trying to abuse the system, and then the users who are maliciously attacking the system. By ignoring GIGO, you end up with a sad list like the <a href="http://www.owasp.org/index.php/Top_10_2007" target="_blank">OWASP Top 10</a>.</span></p>
<h2><span style="color: #2e2e2e">OWASP Top 10 – We Shouldn’t Need It</span></h2>
<p>Despite what that heading says, I’m not saying that the Top 10 is a bad thing. It’s just sad that most of the vulnerabilities can easily be done away with if programmers just take a little extra time and remember to treat everything that a user submits as garbage. Let’s take a look two that should have never made the list, let alone made it to the top two:</p>
<ul>
<li><a href="http://www.owasp.org/index.php/Top_10_2007-A1" target="_blank">#1 – Cross Site Scripting (XSS)</a></li>
<li><a href="http://www.owasp.org/index.php/Top_10_2007-A2" target="_blank">#2 – Injection Flaws (SQL, Command, etc)</a></li>
</ul>
<p>What do both of these problems have in common? Both are caused by applications blindly accepting user input. The problem is made even more sad by the fact that PHP, especially, has many tools available to help mitigate these two types of attacks.</p>
<h2>Filtering Out Cross Site Scripting</h2>
<p>Cross Site Scripting, or XSS, is actually a form of injection, but instead of being executed by the server it is executed by the user’s browser. The classic example, one that happens so frequently it makes an appearance in the satirical <a href="http://www.forumwarz.com/" target="_blank">Forum Warz</a>, is of the guestbook or forum that just displays whatever a user types in back to everyone. Since the Forum (in this case) doesn’t actually do any filtering on the user’s input when they make a post, they can enter things like this:</p>
<p>[cce_html]<br />
U&#8217;ve been pwned!!!!!~~~!!11009&#8220;1~</p>
<p>&lt;script type=&#8221;text/javascript&#8221;&gt;alert(document.cookie);&lt;/script&gt;<br />
[/cce_html]</p>
<p>While the author of the forum may have never intended for users to type in HTML tags, in this case a user did. Now anytime someone visits that post, a pop-up will show the cookie data to the user. An actual attack would probably post that back to a URL and be completely silent. So, how do we get rid of this attack?</p>
<h3>PHP’s Filtering Functions</h3>
<h4>Whitelist HTML Tags with strip_tags()</h4>
<p><a href="http://php.net/manual/en/function.strip-tags.php" target="_blank">strip_tags()</a> can either be used in two ways – remove all the HTML tags in a string or to only remove tags that are not in a white list. This is convenient if you want to allow a subset of HTML to be used in an input form.</p>
<p>[cce_php]<br />
// Grab the user&#8217;s input from POST<br />
$message = $_POST['message'];</p>
<p>// Just remove all the HTML tags<br />
$message = strip_tags($message)</p>
<p>// Only allow basic text formatting such as Bold, Italics, Underline<br />
$whitelist = &#8216;&lt;b&gt;&lt;i&gt;&lt;u&gt;&#8217;;<br />
$message = strip_tags($message, $whitelist);<br />
[/cce_php]</p>
<p>This will filter out that nasty &lt;script&gt; tag in either case. This makes it extremely nice if the app uses a WYSIWYG editor like TinyMCE or FCKEditor that uses HTML natively instead of something like bbcode.</p>
<h3>Convert HTML with htmlentities()</h3>
<p><a href="http://us3.php.net/manual/en/function.htmlentities.php" target="_blank">htmlentities()</a> converts HTML entities (special characters) into their viewable equivalents. For example, to display the ‘less than’ symbol (&lt;) you should actually type in ‘&amp;lt;’ to make sure that browsers display it properly. htmlentities() will take a string and convert anything that has an entity to it.</p>
<p>[cce_php]</p>
<p>// Message is = &lt;b&gt;This is cool!&lt;/b&gt;<br />
$message = $_POST[‘message’];</p>
<p>// Now we’ll get: &amp;lt;b&amp;gt;This is cool!&amp;lt;/b&amp;gt;<br />
echo htmlentities($message);<br />
[/cce_php]</p>
<p>This is useful when you want to take text as it is and return it so that it displays properly. It has the side effect of also destroying attacks that rely on HTML tags since they tags are converted into displayable entities instead of interpreted by the browser. I call this a side effect because I don’t really suggest using htmlentities() in this way. If you are not going to allow HTML at all, strip it with strip_tags().</p>
<h3>Use PHP 5’s filter_input for a common interface</h3>
<p>PHP 5.2.0 introduced a new funtion, <a href="http://php.net/manual/en/function.filter-input.php" target="_blank">filter_input()</a>, which allows for a single function to do different types of filtering and validation.</p>
<p>[cce_php]<br />
// These two should do the exact same thing, strip all HTML Tags<br />
$message = filter_input(INPUT_POST, ‘message’, FILTER_SANITIZE_STRING);<br />
$message = strip_slashes($_POST[‘message’]);<br />
[/cce_php]</p>
<p>While nice, it needs to be expanded a bit to become extremely functional for anything other than basic use.</p>
<h3>Zend_Filter Makes it Way To Easy</h3>
<p><a href="http://framework.zend.com/manual/en/zend.filter.html" target="_blank">Zend_Filter</a>, part of the Zend Framework, exposes a great deal of filtering and makes it easy to integrate with allowing user input. Zend_Filter will filter using:</p>
<ul>
<li>Alphanumeric</li>
<li>Only Alpha (with or without whitespace)</li>
<li>Numeric</li>
<li>HTML Entities</li>
<li>Whitelist HTML Tags</li>
</ul>
<p>[cce_php]<br />
$alnum = new Zend_Filter_Alnum(true); // Filters out everything but letters, numbers, and spaces<br />
$alpha = new Zend_Filter_Alpha(); // Filters out everything but letters, including spaces<br />
$tags = new Zend_Filter_StripTags(); // Filters out just HTML Tags<br />
$message = “Let’s &lt;b&gt;filter&lt;/b&gt; this message out!!!111!”;<br />
echo $alnum-&gt;filter($message); // Lets bfilterb this message out111<br />
echo $alpha-&gt;filter($message); // Letsbfilterbthismessageout<br />
echo $tags-&gt;filter($message); // Let’s filter this message out!!!111!<br />
[/cce_php]</p>
<p>Zend_Filter also allows for <a href="http://framework.zend.com/manual/en/zend.filter.filter_chains.html" target="_blank">Filter Chains</a> that allow a programmer to add a bunch of filters and apply them all at once. This is useful if you want to strip out all the HTML, and then strip out any remaining special characters, unlike the first filter example where the text inside the tags is left.</p>
<p>The real jewel with Zend_Filter comes when used with <a href="http://framework.zend.com/manual/en/zend.form.html" target="_blank">Zend_Form</a>. Zend_Form allows for forms to be built in PHP and then sent to the browser. When generating elements for the form, the programmer has the option to add filters and validations to elements that are fired off when the form is processed. A full tutorial is beyond the scope of this article, but the documentation shows how to use filters on the elements <a href="http://framework.zend.com/manual/en/zend.form.elements.html#zend.form.elements.filters" target="_blank">here</a>.</p>
<h2>Remember, Don’t Trust Your Users</h2>
<p>I’ll tackle Injection attacks in another post, as there are different types of injection attacks. For now though, always remember to sanitize and filter <strong><em><span style="color: #ff0000;">ANY</span></em></strong> input that you accept from the user. While most users are not trying to be harmful, there are ones out there that are. It also means one less thing you have to worry about being a flaw or bug in an application.</p>
<p><strong>PS: Hungarian Notation</strong></p>
<p><span style="color: #2e2e2e;">One thing that may be useful that I picked up from Joel Spolsky is the concept of (proper) <a href="http://www.joelonsoftware.com/articles/Wrong.html" target="_blank">Hungarian Notation</a>. Have a read through his post for the proper way to do Hungarian Notation and why it makes sense. </span></p>
]]></content:encoded>
			<wfw:commentRss>http://blogs.tankersleywebsolutions.com/2009/11/03/dont-trust-your-users/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Hashing Is Not Encryption</title>
		<link>http://blogs.tankersleywebsolutions.com/2009/10/14/hashing-is-not-encryption/</link>
		<comments>http://blogs.tankersleywebsolutions.com/2009/10/14/hashing-is-not-encryption/#comments</comments>
		<pubDate>Thu, 15 Oct 2009 03:34:58 +0000</pubDate>
		<dc:creator>chris</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[TWS Software]]></category>
		<category><![CDATA[Tutorials]]></category>
		<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[crypto]]></category>
		<category><![CDATA[hashing]]></category>
		<category><![CDATA[PHP]]></category>

		<guid isPermaLink="false">http://blogs.tankersleywebsolutions.com/?p=235</guid>
		<description><![CDATA[One of my pet peeves when talking with other programmers is when they use the wrong terminology. One of the most common ones that comes up for me is the issue of Encryption, and most of the time people are not encrypting, but hashing. And yes, there is a distinction.
What Hashing Is
Hashing is a mechanism [...]]]></description>
			<content:encoded><![CDATA[<p>One of my pet peeves when talking with other programmers is when they use the wrong terminology. One of the most common ones that comes up for me is the issue of Encryption, and most of the time people are not encrypting, but hashing. And yes, there is a distinction.</p>
<h2>What Hashing Is</h2>
<p>Hashing is a mechanism for figuring out if two things are similar and is a one-way process. You take an object (file, string of text, ISO) and convert it to a fixed length string. You can then use this key to see if something else is the same thing.</p>
<p>The most common example of this is with large downloads. All the major Linux distributions will give an MD5 hash for their downloads so that you can verify that the file was not corrupted during transmission. You can run the ISO file through an MD5 generator which will give you back a 32 character string. If that string matches what Canonical says was their MD5, you have a match and your ISO is good.</p>
<p>In programming, one of the most common methods for hashing is password. In this case it is done for two reasons:</p>
<ol>
<li>You never, <em>ever</em> store passwords in Plaintext in a database</li>
<li>You never should care what the user&#8217;s password is</li>
</ol>
<p>Since #2 means you never need to know what the hash stands for, Hashing is a light-weight alternative to encryption while still providing security.</p>
<p><code lang="php">$password = md5($_POST['password']);<br />
$username = $_POST['username'];<br />
$result = mysql_query("SELECT username, password FROM user_accounts WHERE password = '$password' AND username = '$username'");<br />
if( mysql_num_rows($result) == 1 ) {<br />
echo 'Found a proper account!';<br />
} else {<br />
echo 'Invalid username and Password';<br />
}<br />
</code></p>
<h3>Salts</h3>
<p>No, not Bacon Salt. Salts are additional bits of text you add to something before hashing to prevent someone from cracking the hashes that you are using.</p>
<p><code lang="php"> $salt = 'ThisIsAReallyLongAndSecureString';<br />
$hash = md5($_POST['password'] .  $salt);<br />
echo md5($_POST['password']) . ' != ' . $hash;<br />
</code></p>
<p>Salts are only useful if you are trying to use Hashing for security reasons, like storing passwords. If you are looking for just verification then a salt is useless. If you are using hashing for security purposes, ALWAYS USE A SALT.</p>
<h3>Proper Hashing</h3>
<p>Prior to PHP 5.1.2, the two most common ways to hash a file was to use either of the built-in hashing functions for MD5 or SHA1. Due to the fact that MD5 and SHA1 are considered insecure I don&#8217;t recommend using them even with a salt. You can generate a hash very easily using either MD5 or SHA1 and it should work on every single platform.</p>
<p><code lang="php">$sha1 = sha1('This is a string');<br />
$md5 = md5('This is a string');<br />
</code></p>
<p>Since 5.1.2 PHP has added a proper hashing library that allows you to take advantage of more powerful algorithms. It is turned on by default, but if PHP is compiled by hand it can be disabled.</p>
<p>You can find out what algorithms are installed on a system by running the <a href="http://us2.php.net/manual/en/function.hash-algos.php" target="_blank">hash_algos()</a> function. This returns an array of different algorithms that are installed on the system and that are available for use. These are also the names that can be used with the companion function <a href="http://us2.php.net/manual/en/function.hash.php" target="_blank">hash()</a>. So, if you wanted to store a password in the database the proper way using a hash, you would do something like the following:</p>
<p><code lang="php">// Our Salt<br />
$salt = 'SuperSecretSaltNoOneWillEverFindOutAbout';<br />
// The user-supplied, unhashed password and username<br />
$usPassword = $_POST['password'];<br />
$sUsername = mysql_real_escape_string($_POST['username']);<br />
// Generate a SHA-384 hash using our salt<br />
$sPassword = hash('sha384', $usPassword . $salt);<br />
// Save it to the DB<br />
mysql_query("UPDATE user_accounts SET password = '$sPassword' WHERE username = '$sUsername'");</code></p>
<h2>Fine, what is Encryption then?</h2>
<p>If Hashing is a one-way street, Encryption is two-way. You would use encryption whenever you need to safely store information but need to retrieve it later. (Again, you almost never need to know what a user&#8217;s password is, so why use encryption?) Encryption is also a heavier action than hashing.</p>
<p>Say we had a table, user_accounts, which had the following fields:</p>
<ul>
<li>id</li>
<li>username</li>
<li>password</li>
<li>name</li>
<li>social_security_number</li>
<li>address_street</li>
<li>address_city</li>
<li>address_state</li>
<li>address_zip</li>
<li>cc_number</li>
<li>cc_type</li>
<li>cc_cvv</li>
<li>cc_exp_date</li>
</ul>
<p>We would want to hash the password obviously. ID, username, and name we can probably not worry about doing anything too. Everything else though we would want to encrypt as all that information can be used in a very destructive manner if the database is stolen, but we need to use that data. Encryption would allow us to store that information in the database and sleep at night, yet still pull it back up when we needed it.</p>
<h3>Keys</h3>
<p>Keys, unlike Salts in hashes, are required. The key is used during the encryption process as a constant. If you use the wrong key you will not get back what you stored as the key is actually used for both encryption and decryption. Like a Salt, you&#8217;ll want to store this somewhere such as a file with limited read access.</p>
<p>For security reasons you will also want to look at a key rotation plan. One advantage that hashing has over encryption is that it is not meant to turn the random output of the hash back into something useful, where encryption is designed for just that purpose. If someone gets a hold of the encryption key, it is trivial to decrypt the data.</p>
<p>You will want to consider a key rotation plan because of this. Every set number of days you will want to decrypt all the data using the old key and re-encrypt it with the new key. Yes, it is time consuming, but that is the tradeoff for using encryption and staying secure.</p>
<h3 style="font-size: 1.17em;">Encryption Made Easy</h3>
<p>PHP can do encryption as well as hashing. I personally prefer using the Mcrypt library that is available on most Linux systems, but PHP can also use OpenSSL. Encryption is a fairly heavy weight process and requires a bit of setup to get going. I&#8217;ve created a simple class for setting up and using Mcrypt at <a href="http://code.google.com/p/tws-code/">http://code.google.com/p/tws-code/</a> .</p>
<p><code lang="php" escaped="true">$key = 'SuperSecretKey';<br />
$twsMcrypt = new Tws_Mcrypt($key);<br />
$encryptedString = $twsMcrypt->encrypt('This is a secret message');<br />
$unencryptedString = $twsMcrypt->decrypt($encryptedString');</code></p>
<p>Tws_Mcrypt can also take a second constructor argument to specify the type of encryption to use, otherwise it defaults to RIJNDAEL_128. It also encodes the encrypted string in Base64 to make storage easier, so if you encrypt something using Tws_Mcrypt and try to decrypt it straight, make sure you Base64 decode it first.</p>
<h2>&#8220;Unless you are a cryptanalyst, don&#8217;t do your own crypto&#8221;</h2>
<p>One final comment on hashing and encryption. The algorithms that are used in either case are tried and tested algorithms that are hard to crack and, in some cases, extremely sophisticated. People much, much smarter have taken the time to develop them and you, me, nor anyone that is not a cryptanalyst will do better.</p>
<p>Don&#8217;t think that the nifty encryption algorithm you came up with last night while you were in the zone will be any better than the ones that ship in PHP or in libraries like Mcrypt or OpenSSL. It won&#8217;t be and will only put you at risk.</p>
<h2>So which to use?</h2>
<p>Use Hashing when:</p>
<ul>
<li>You don&#8217;t care what the actual data is</li>
<li>You just need to do verification</li>
<li>You need something extremely light-weight</li>
</ul>
<p>Use Encryption when:</p>
<ul>
<li>Data needs to be secured, but pulled back up later</li>
</ul>
<p>Keep all this in mind next time you are talking to someone about how your application works. Don&#8217;t tell them you are encrypting passwords in the database when what you are really doing is hashing them. Don&#8217;t think that using straight MD5 is a viable means for data security.</p>
<p>Hopefully this will help you choose which type of security based on what you are doing as well.</p>
]]></content:encoded>
			<wfw:commentRss>http://blogs.tankersleywebsolutions.com/2009/10/14/hashing-is-not-encryption/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Yes, the Zend Framework is Complex</title>
		<link>http://blogs.tankersleywebsolutions.com/2009/09/18/yes-the-zend-framework-is-complex/</link>
		<comments>http://blogs.tankersleywebsolutions.com/2009/09/18/yes-the-zend-framework-is-complex/#comments</comments>
		<pubDate>Sat, 19 Sep 2009 03:28:23 +0000</pubDate>
		<dc:creator>chris</dc:creator>
				<category><![CDATA[Programming]]></category>

		<guid isPermaLink="false">http://blogs.tankersleywebsolutions.com/?p=219</guid>
		<description><![CDATA[Over the last few days, I&#8217;ve seen two discussions on mailing lists that I subscribe to. One was on the Zend Framework MVC list and the complexity of Zend Framework and and the second was on the OpenBSD misc mailing list on the degradation of the computer industry as a whole.
I&#8217;ve been programming for as [...]]]></description>
			<content:encoded><![CDATA[<div id="attachment_218" class="wp-caption alignright" style="width: 160px"><a href="http://www.flickr.com/photos/steveluscher/394265766/"><img class="size-thumbnail wp-image-218  " style="float: left" title="394265766_cb60926e8a" src="http://blogs.tankersleywebsolutions.com/wp-content/uploads/2009/09/394265766_cb60926e8a-150x150.jpg" alt="Photo by steveluscher (via Flickr)" width="150" height="150" /></a><p class="wp-caption-text">Photo by steveluscher (via Flickr)</p></div>
<p>Over the last few days, I&#8217;ve seen two discussions on mailing lists that I subscribe to. One was on the <a href="http://www.nabble.com/so-complex!-to25465392.html#a25467394" target="_blank">Zend Framework MVC</a> list and the complexity of Zend Framework and and the second was on the <a href="http://marc.info/?l=openbsd-misc&amp;w=2&amp;r=1&amp;s=old+school+unix&amp;q=b" target="_self">OpenBSD misc</a> mailing list on the degradation of the computer industry as a whole.</p>
<p>I&#8217;ve been programming for as long as I can remember, starting with BASIC on an old Tandy that we just happened to have since my father worked at Radio Shack years ago. From there I had a dry spell until the web started to take off and I learned HTML (yes, it isn&#8217;t a programming language but a markup language, but humor me). Javascript was about as tough as I would get until dabbling with some C++ books during high school.</p>
<p>During college I was blessed with having a great teacher that taught me one thing: Programming is an art, and it takes patience and learning to get it right. I had him for two years across multiple languages (COBOL, RPG ILE, Visual Basic .NET, C++, C#, AS/400 CL) and every single class was the same thing, just a different syntax. Why?</p>
<p>He was teaching how to <em>program</em>, not how to slap some language verbs together and get a running program. A programming language was nothing more than a tool, and there is a reason that there are so many languages out there. Define a problem, pick the appropriate language(s), and develop a solution. VB isn&#8217;t the answer to everything, and neither is C#, Python, or PHP. If you need a quick and dirty Windows app, use VB.NET/C#. Need a web app, pick Python, PHP, or .NET.</p>
<p>Of course, a major part of learning the art of programming is the ability to troubleshoot. If code isn&#8217;t working, it is a programmer&#8217;s job to find out why. It is also the programmers job to keep on learning and diving into the more complex nature of languages to better themselves, their code, and their ability to move forward.</p>
<p>My favorite language thus far is PHP. The strength of PHP and its weakness is that PHP allows anyone to pick up the code and develop extremely powerful web applications (or desktop apps if one is inclined) with little knowledge of what they are doing. One doesn&#8217;t need to know what they are actually doing when there are multitudes of tutorials out there that just spoon-feed up-and-coming &#8216;programmers&#8217; solutions. Take a look at <a href="http://stackoverflow.com" target="_blank">stackoverflow.com</a>&#8217;s PHP questions and you&#8217;ll see what I mean.</p>
<p>The main gripe of the original author of the Zend Framework thread was that Zend Framework was too complex to be useful to new programmers. No, it isn&#8217;t. Zend Framework is complex and hard to use to programmers that are lazy and can&#8217;t be bothered to actually learn what is going on with the tools that they are using (though I will admit I still am dismayed at the new Bootstrapping process, but just because I don&#8217;t like it doesn&#8217;t make it hard, and I see where it is going).</p>
<p>Each new version of Zend Framework is more complex than the last but that is a trade-off of progress. As a programmer this should not be an issue. You have the source code and what I consider some of the greatest documentation for a framework out there, and there are some great people leading the team. If a framework and its core principles are too hard, either switch frameworks/languages or learn. Don&#8217;t complain (unless it&#8217;s a bug, but then ZF is open source so just fix the bug).</p>
<h5 style="text-align: right;">*Just as a note, I&#8217;m not saying that function-based programming is any easier or better. The Drupal and Wordpress source code can be just as complex as the Zend Framework and it&#8217;s OO-based approach.</h5>
]]></content:encoded>
			<wfw:commentRss>http://blogs.tankersleywebsolutions.com/2009/09/18/yes-the-zend-framework-is-complex/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>BiffCMS is now Kiroku!</title>
		<link>http://blogs.tankersleywebsolutions.com/2009/06/04/biffcms-is-now-kiroku/</link>
		<comments>http://blogs.tankersleywebsolutions.com/2009/06/04/biffcms-is-now-kiroku/#comments</comments>
		<pubDate>Fri, 05 Jun 2009 04:26:10 +0000</pubDate>
		<dc:creator>chris</dc:creator>
				<category><![CDATA[Personal]]></category>
		<category><![CDATA[Software]]></category>
		<category><![CDATA[TWS Software]]></category>
		<category><![CDATA[Kiroku]]></category>

		<guid isPermaLink="false">http://blogs.tankersleywebsolutions.com/?p=210</guid>
		<description><![CDATA[A few weeks ago BiffCMS changed names to Kiroku (which means Document in Japanese). This was mostly motivated by the fact that BiffCMS, in its current incarnation, bears little resemblence to what BiffCMS was even a year ago. A great deal of work has been done under the hood as it was converted over to [...]]]></description>
			<content:encoded><![CDATA[<p>A few weeks ago BiffCMS changed names to <a href="http://code.google.com/p/kiroku">Kiroku</a> (which means Document in Japanese). This was mostly motivated by the fact that BiffCMS, in its current incarnation, bears little resemblence to what BiffCMS was even a year ago. A great deal of work has been done under the hood as it was converted over to Zend Framework and the UI is undergoing a complete overhaul that removes the old table-like layout of most of the pages.</p>
<p>jQuery is being employed in the Adminstration area to make it function much easier and cleaner than ever before:<br />
<a href="http://blogs.tankersleywebsolutions.com/wp-content/uploads/2009/06/biffcms-old.png"><img class="size-thumbnail wp-image-208" title="BiffCMS\'s Page Admin" src="http://blogs.tankersleywebsolutions.com/wp-content/uploads/2009/06/biffcms-old-150x150.png" alt="" width="150" height="150" /></a> <a href="http://blogs.tankersleywebsolutions.com/wp-content/uploads/2009/06/kiroku-pages.png"><img class="size-thumbnail wp-image-209" title="Kiroku\'s Revamped Pages Admin" src="http://blogs.tankersleywebsolutions.com/wp-content/uploads/2009/06/kiroku-pages.png" alt="" width="150" height="150" /></a></p>
<p>The Plugin model has been revamped from the old BiffCMS months ago as well as the addition of Sections. A nicer WYSIWYG editor is in place over the old BiffCMS. All in all, Kiroku has grown a lot since BiffCMS was started by me years ago as a quick way to design and maintain web pages.</p>
<p>There are a few other projects that I&#8217;m working on and, as they grow, are moving away from the Biff name. The BiffAPI most of my code was built on in the PHP4 days is no longer worthwhile since I&#8217;ve moved on to the Zend Framework, so its appropriate that these project names change.</p>
<p>If you&#8217;re interested in working with Kiroku, just drop me a line through <a href="mailto:chris@tankersleywebsolutions.com">e-mail</a> or hit me up on <a href="http://www.twitter.com/dragonmantank" target="_blank">Twitter</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://blogs.tankersleywebsolutions.com/2009/06/04/biffcms-is-now-kiroku/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>php&#124;tek 2009 In Review</title>
		<link>http://blogs.tankersleywebsolutions.com/2009/05/25/phptek-2009-in-review/</link>
		<comments>http://blogs.tankersleywebsolutions.com/2009/05/25/phptek-2009-in-review/#comments</comments>
		<pubDate>Tue, 26 May 2009 01:42:10 +0000</pubDate>
		<dc:creator>chris</dc:creator>
				<category><![CDATA[Personal]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[phptek]]></category>
		<category><![CDATA[tek09]]></category>

		<guid isPermaLink="false">http://blogs.tankersleywebsolutions.com/?p=187</guid>
		<description><![CDATA[I got the chance to spend last week in Chicago for php&#124;tek 2009, perhaps one of the premier PHP conventions in the US. Some of the most well known names in PHP were in attendance and gave some great presentations.

Among my time spent getting to know the PHP community and finally getting to meet the [...]]]></description>
			<content:encoded><![CDATA[<p>I got the chance to spend last week in Chicago for <a href="http://tek.mtacon.com/" target="_blank">php|tek 2009</a>, perhaps one of the premier PHP conventions in the US. Some of the most well known names in PHP were in attendance and gave some great presentations.</p>
<p><span id="more-187"></span></p>
<p>Among my time spent getting to know the PHP community and finally getting to meet the people I talk with on #phpc, I managed to attend a few sessions.</p>
<p><strong>Day 1</strong></p>
<p>While I wasn&#8217;t present for the tutorial days, I was there for the main body of the conference. <a href="http://gravitonic.com/" target="_blank">Andrei Zmievski</a>, after being released from captivity, assured us that at some point PHP6 will be released and will contain some great features (granted, <span class="speaker">Sara Golemon showed us exactly why PHP 5.3 is going to be the next big thing to look forward to with features such as lambdas, smarter garbage collection, and other things that are as cool as velociraptors). </span></p>
<p>From there I attended <a href="http://www.hauser-wenz.de/s9y/" target="_blank">Christian Wenz</a>&#8217;s talk on Ajax testing and the tools that can be used. I wanted to hit up some of the talks that would help me out at work, so from there I listened to a talk by Mike Pavlak about running PHP on the IBM i brand of servers (who knew that PHP was a first class citizen on the i?). <a href="http://www.priebsch.de/" target="_blank">Stefan Priebsch</a> gave some pointers on how to build an MVC application, I listened to <a href="http://netevil.org/" target="_blank">Wez Furlong</a> give a great talk on getting things done by using the Scrum method of application development planning, and I finished out the day listening to a talk by <a href="http://shiflett.org/" target="_blank">Chris Shiflett</a> on security centered design and common mistakes that sites make in their assumptions with user security.</p>
<p>I rounded out the day by listening to <a href="http://www.dragonbe.com/" target="_blank">Michelango van Dam</a> give a great Uncon talk about using PHPUnit for Test Driven Development.</p>
<p><strong>Day 2</strong></p>
<p>My second day started off with the earlier mentioned talk by <a href="http://blog.libssh2.org/" target="_blank">Sara Golemon</a> on the new features in PHP 5.3 (my opinion &#8211; I cannot <em>wait</em> until PHP 5.3 arrives). After that it was a talk by <a href="http://derickrethans.nl" target="_blank">Derick Rethans</a> on K.I.S.S (Keep It Simple Stupid) design tips for web applications, <a href="http://blog.casey-sweat.us/" target="_blank">Jason Sweat</a> on common design patterns for use on the web, and then over to <a href="http://paul-m-jones.com/" target="_blank">Paul M. Jones</a> for a talk on organizing your web project (thankfully I&#8217;m doing it right on Kiroku and Congregate!). I got to see <a href="http://www.rcbowen.com/" target="_blank">Rich Bowen</a> talk about mod_rewrite, and I finished off my day attending to hack-a-thon (more on this in a later post). There I met <a href="http://saltybeagle.com/" target="_blank">Brett Bieber</a> who works on the <a href="http://pear.php.net" target="_blank">PEAR2</a> project who showed me how to start testing PEAR2, the new features it will bring, and even gave me a shirt!</p>
<p><strong>Day 3</strong></p>
<p>Day three was the last official day of the conference. <a href="http://seancoates.com/" target="_blank">Sean Coates</a> gave a talk about tokenizing in PHP and how to leverege it for a developers own use, <a href="http://blog.calevans.com/" target="_blank">Cal Evans</a> gave a great talk on why telecommuting is no longer a perk but an expectation for PHP developers, and <a href="http://terrychay.com/blog/" target="_blank">Terry Chay</a> gave an empassion, funny, (and moderately curse filled) ending keynote on why PHP developers are engineers and why that is what makes us stand out in the crowd.</p>
<p>This day finished off with a talk by Paul M. Jones on why personal frameworks suck but are a natural right of passage, and Michelango van Dam gave a second Uncon about Continuous Integration.</p>
<p><strong>My Quick Take</strong></p>
<p>This years php|tek was even better than last years. Not only did I get to meet a ton of great people but I learned a lot more than I could have even hoped. The PHP language is poised to continue to be one of the best, if not the best, web language that there is despite opposition from Sun/Oracle&#8217;s Java and Microsoft&#8217;s .NET. PHP 5.3 and 6 are adding sorely needed constructs to the language that will do nothing but improve the quality of software that developers can write.</p>
<p>For all the crap that PHP takes, there isn&#8217;t anything I can see in the upcoming releases that will make me want to switch.</p>
<p>I want to thank all the people that I met there, and if I left anyone off the list I apologize:</p>
<p>@enygma, @sweatje, @nateabele, @brandonsavage, @EliW, @tswicegood, @elazar, @DragonBe, @CalEvans (even if he doesn&#8217;t remember me) and everyone else who I didn&#8217;t catch their twitter handles or irc names.</p>
]]></content:encoded>
			<wfw:commentRss>http://blogs.tankersleywebsolutions.com/2009/05/25/phptek-2009-in-review/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Major Upgrade to BiffCMS</title>
		<link>http://blogs.tankersleywebsolutions.com/2009/02/07/major-upgrade-to-biffcms/</link>
		<comments>http://blogs.tankersleywebsolutions.com/2009/02/07/major-upgrade-to-biffcms/#comments</comments>
		<pubDate>Sat, 07 Feb 2009 05:12:46 +0000</pubDate>
		<dc:creator>chris</dc:creator>
				<category><![CDATA[TWS Software]]></category>
		<category><![CDATA[This Site]]></category>
		<category><![CDATA[BiffCMS]]></category>
		<category><![CDATA[TWS]]></category>
		<category><![CDATA[Zend Framework]]></category>

		<guid isPermaLink="false">http://blogs.tankersleywebsolutions.com/?p=160</guid>
		<description><![CDATA[One of the nice things about switching BiffCMS to using the Zend Framework from the now extremely old and not-PHP5 BiffAPI that it used to run on is flexibility with power. Due to Zend Framework&#8217;s nature of allowing the programmer to do what they want instead of forcing them into a design paradigm, BiffCMS is [...]]]></description>
			<content:encoded><![CDATA[<p>One of the nice things about switching <a href="http://code.google.com/p/biffcms">BiffCMS</a> to using the <a href="http://framework.zend.com">Zend Framework</a> from the now extremely old and not-PHP5 BiffAPI that it used to run on is flexibility with power. Due to Zend Framework&#8217;s nature of allowing the programmer to do what they want instead of forcing them into a design paradigm, BiffCMS is now more modular.</p>
<p><strong>What was overhauled?</strong></p>
<p>The basic folder structure and some plumbing were overhauled in the last few days. The introduction of a &#8216;plugins&#8217;, a &#8217;sections&#8217;, and a better theme system were all moved around and coded to allow for easier development. If you were using the Zend Framework version of BiffCMS all you will need to do is move some files around, but this is not a simple &#8216;overwrite files&#8217; kind of upgrade.</p>
<p><strong>Plugins</strong></p>
<p>The heart of BiffCMS has always been Modules, which dictate what pages you can add to your site through BiffCMS. Since this has a much different term to Zend Framework developers these are now renamed Plugins and are much more easy to develop. Using the new &#8216;plugins&#8217; folder, each plugin is now fully self contained inside its own folder. Need to install a new plugin? Drop it into the &#8216;plugins&#8217; folder and go from there (still needs to be manually entered into the DB, but work on installation is coming along).  I&#8217;ve also added an Externallink plugin that allows pages that direct to outside URLs.</p>
<p><strong>Sections</strong></p>
<p>BiffCMS is built using Zend Framework&#8217;s MVC components and therefore has full support for Zend Framework modules (collections of Controllers and View Scripts). BiffCMS calls these Sections and they can be used when a simple page Plugin is not enough. Drop them into the &#8217;sections&#8217; folder and add them to the index.php page just like a regular Zend Framework module. Work is also progressing on allowing Sections to be enabled and disabled via the admin GUI.</p>
<p><strong>Theming</strong></p>
<p>The last thing a web developer wants is for his website to look like everyone elses. BiffCMS now has support for packaged themes, much like the BiffAPI version used to. Just create a folder containing at least a &#8216;layout.phtml&#8217; and an &#8216;admin-layout.phtml&#8217;, drop it into the &#8216;www/themes/&#8217; folder, and you can select it from the System Config portion of the Admin. These are just regular Zend Framework layout files so existing layouts can be easily ported.</p>
<p><strong>Administration</strong></p>
<p>Along with the above changes, BiffCMS now supports adding and editing users (deleting coming soon!), the beginnings of a System Config section to allow low level config changes like Themes, and a better Plugin management system.</p>
<p>If you want to check it out, head over to <a href="http://code.google.com/p/biffcms">http://code.google.com/p/biffcms</a> and check out a copy of the SVN. Within a few weeks there will be a formal release as some loose ends are tied up.</p>
]]></content:encoded>
			<wfw:commentRss>http://blogs.tankersleywebsolutions.com/2009/02/07/major-upgrade-to-biffcms/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Tankersley Web Solutions running BiffCMS</title>
		<link>http://blogs.tankersleywebsolutions.com/2009/01/18/tankersley-web-solutions-running-biffcms/</link>
		<comments>http://blogs.tankersleywebsolutions.com/2009/01/18/tankersley-web-solutions-running-biffcms/#comments</comments>
		<pubDate>Sun, 18 Jan 2009 05:43:21 +0000</pubDate>
		<dc:creator>chris</dc:creator>
				<category><![CDATA[TWS Software]]></category>
		<category><![CDATA[This Site]]></category>
		<category><![CDATA[BiffCMS]]></category>
		<category><![CDATA[TWS]]></category>
		<category><![CDATA[Zend Framework]]></category>

		<guid isPermaLink="false">http://blogs.tankersleywebsolutions.com/?p=156</guid>
		<description><![CDATA[I&#8217;ve been meaning to do this for a while since BiffCMS has stablized to the point where I feel comfortable running it in production since switching it to Zend Framework from the old BiffAPI that it had been running. This is good since I just finished setting up and working on the website for Dragonlance: [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve been meaning to do this for a while since <a href="http://code.google.com/p/biffcms">BiffCMS</a> has stablized to the point where I feel comfortable running it in production since switching it to Zend Framework from the old BiffAPI that it had been running. This is good since I just finished setting up and working on the website for <a href="http://www.dlwhatif.com">Dragonlance: What If?</a>, a new MUSH that will be going into beta this week.</p>
<p>Want to know how easy it is to get up and running with BiffCMS? I installed the app, ported the layout, and added a few pages in just about four hours total. Less than half of a day and I&#8217;ve got a site that I&#8217;m happy with and will have to do less to maintain than the straight Zend Framework-based site that was there before.</p>
<p>Want to try out BiffCMS? Head on over to the <a href="http://code.google.com/p/biffcms">Google Code site</a> and check out the latest working copy. I&#8217;ll be bundling a full release here within a week or so.</p>
]]></content:encoded>
			<wfw:commentRss>http://blogs.tankersleywebsolutions.com/2009/01/18/tankersley-web-solutions-running-biffcms/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Biff Project Manager Launched</title>
		<link>http://blogs.tankersleywebsolutions.com/2008/11/19/biff-project-manager-launched/</link>
		<comments>http://blogs.tankersleywebsolutions.com/2008/11/19/biff-project-manager-launched/#comments</comments>
		<pubDate>Thu, 20 Nov 2008 03:45:30 +0000</pubDate>
		<dc:creator>chris</dc:creator>
				<category><![CDATA[Personal]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[Software]]></category>
		<category><![CDATA[TWS Software]]></category>
		<category><![CDATA[This Site]]></category>

		<guid isPermaLink="false">http://blogs.tankersleywebsolutions.com/?p=144</guid>
		<description><![CDATA[Another project of mine has been launched &#8211; Biff Project Manager. Biff Project Manager is a project management system that I am building to replace my by-hand method of project management. The first SVN commit has been made and you can check out a fresh copy from Google Code.
What does it do?
Right now not a [...]]]></description>
			<content:encoded><![CDATA[<p>Another project of mine has been launched &#8211; <a href="http://code.google.com/p/biffprojectmanager">Biff Project Manager</a>. Biff Project Manager is a project management system that I am building to replace my by-hand method of project management. The first SVN commit has been made and you can check out a fresh copy from Google Code.</p>
<p><strong>What does it do?</strong></p>
<p>Right now not a whole lot. You can add projects and tasks to those projects. Thanks to the beauty of jQuery and AJAX you can edit the tasks right there in the table without having to go to any special pages so updating your tasks is as simple as using a spreadsheet. It is great for simply noting down what you need to do but in the coming weeks it will be expanded to do much more. Time spent on each task is recorded as well as who completed the task.</p>
<p><strong>Installation</strong></p>
<p>Installation is fairly easy. Check out a copy from SVN and put it up on your web host. You will need to edit the &#8216;public/.htaccess&#8217; file&#8217;s rewrite rule to the path that you unpacked it to. Once that is done run the SQL setup script in &#8216;data/db/base.sql&#8217; to set up a basic database. That&#8217;s all there is!</p>
]]></content:encoded>
			<wfw:commentRss>http://blogs.tankersleywebsolutions.com/2008/11/19/biff-project-manager-launched/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
