<?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>Project 2061 Techlog</title>
	<atom:link href="http://techlog.p2061.org/feed/" rel="self" type="application/rss+xml" />
	<link>http://techlog.p2061.org</link>
	<description>Blogging from Project 2061 technology group</description>
	<lastBuildDate>Fri, 05 Mar 2010 23:27:57 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.2</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Rewriting URLs on IIS6</title>
		<link>http://techlog.p2061.org/2010/03/05/rewriting-urls-on-iis6/</link>
		<comments>http://techlog.p2061.org/2010/03/05/rewriting-urls-on-iis6/#comments</comments>
		<pubDate>Fri, 05 Mar 2010 23:27:57 +0000</pubDate>
		<dc:creator>BrianS</dc:creator>
				<category><![CDATA[System Administration]]></category>
		<category><![CDATA[Web Development]]></category>
		<category><![CDATA[CakePHP]]></category>
		<category><![CDATA[iirf]]></category>
		<category><![CDATA[mod_rewrite]]></category>

		<guid isPermaLink="false">http://techlog.p2061.org/?p=305</guid>
		<description><![CDATA[One of the nice things about CakePHP is that it attempts to make a site more friendly to the average web site visitor by creating easier-to-remember URLs. There are a few techniques that CakePHP uses, but for the sake of this conversation we&#8217;ll focus on one way in particular: apache&#8217;s mod_rewrite functionality. Using mod_rewrite, URLs [...]]]></description>
			<content:encoded><![CDATA[<p>One of the nice things about CakePHP is that it attempts to make a site more friendly to the average web site visitor by creating easier-to-remember URLs. There are a few techniques that CakePHP uses, but for the sake of this conversation we&#8217;ll focus on one way in particular: apache&#8217;s mod_rewrite functionality. Using mod_rewrite, URLs that would normally include the controller file (index.php) and a querystring can be rewritten as a simple file path.</p>
<p>Microsoft doesn&#8217;t include mod_rewrite-style functionality in IIS by default, though it has created an <a href="http://www.iis.net/expand/URLRewrite">extension for IIS7</a>. Since we are currently using IIS6 the extension isn&#8217;t an option for us. Fortunately there are a few other options available, including an open-source project called <a href="http://www.codeplex.com/IIRF">Ionics Isapi Rewrite Filter</a> (IIRF). IIRF is an ISAPI filter that is very similar to mod_rewrite in terms of functionality. After some testing I&#8217;ve found this filter works almost perfectly for enabling CakePHP&#8217;s friendly URLs.</p>
<p><strong>Getting Started</strong></p>
<p>Installation is painless and requires only a few steps. The following is based on the IIRF 2.0.1.15 release which does not include an installer:</p>
<ol>
<li>Extract the files from the IIRF archive to a folder on the server.</li>
<li>Open the properties of the IIS root &#8220;Web Sites&#8221; folder or the specific site that needs IIRF.</li>
<li>In the &#8220;ISAPI Filters&#8221; tab create a new entry for IIRF; name the new filter (e.g. &#8220;IIRF&#8221;); specify the IIRF DLL located with the extracted IIRF files at \bin\IIRF.dll.</li>
<li>Ensure that the IIS user has read/execute access to the IIRF DLL and read/write access to any directories that will be used for logging.</li>
<li>Restart IIRF.</li>
</ol>
<p>IIRF should now be installed, but I&#8217;ve found that sometimes the filter won&#8217;t appear to be active in the &#8220;ISAPI Filters&#8221; tab until it has been used the first time. To enable IIRF all you have to do is create a file called IIRF.ini and place it in the web site root folder or in the root of a virtual directory. This file contains any local configuration directives (such as log directory) and URL rewriting rules.</p>
<p><strong>The obligatory gotcha</strong></p>
<p>I mentioned before that the filter works <em>almost</em> perfectly. The only situation where I&#8217;ve had problems up to now is if the URL contains one or more space characters. The IIRF log indicates that a URL with a space is being parsed correctly and returning a valid URL. And yet the web server reports a 404 error.</p>
<p>I&#8217;ve only done testing when the final URL references a physical file, but based on a conversation in the support forum I suspect this problem also affects parameters in the querystring. I haven&#8217;t yet had a chance to fully investigate the issue, so I don&#8217;t have a  work-around yet when the issue affects physical files. There does, however, appear to be a work-around for spaces in the querystring.</p>
<p>For now I have decided to ensure that any URLs parsed by IIRF that will point to a physical file/directory does not contain spaces.</p>
<p><strong>References</strong></p>
<p>CakePHP usage:</p>
<ul>
<li><a href="http://iirf.codeplex.com/Thread/View.aspx?ThreadId=100341">CakePHP, IIRF REQUEST_FILENAME problem</a></li>
<li><a href="http://techlog.p2061.org/wp-content/uploads/2010/03/iirf.ini_.txt">Sample IIRF.ini for CakePHP  installation</a></li>
</ul>
<p>Space-in-URL problems:</p>
<ul>
<li><a href="http://iirf.codeplex.com/Thread/View.aspx?ThreadId=66377">Url rewrite and whitespaces</a></li>
<li><a href="http://iirf.codeplex.com/Thread/View.aspx?ThreadId=203696">Space character in URL: rewrite appears correct, 404 returned</a></li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://techlog.p2061.org/2010/03/05/rewriting-urls-on-iis6/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Moving from Microsoft Access to MySQL</title>
		<link>http://techlog.p2061.org/2010/02/26/moving-from-microsoft-access-to-mysql/</link>
		<comments>http://techlog.p2061.org/2010/02/26/moving-from-microsoft-access-to-mysql/#comments</comments>
		<pubDate>Fri, 26 Feb 2010 17:58:40 +0000</pubDate>
		<dc:creator>BrianS</dc:creator>
				<category><![CDATA[IERI]]></category>
		<category><![CDATA[MySQL]]></category>
		<category><![CDATA[Web Development]]></category>
		<category><![CDATA[asp]]></category>
		<category><![CDATA[msaccess]]></category>

		<guid isPermaLink="false">http://techlog.p2061.org/?p=298</guid>
		<description><![CDATA[We recently decided to make a public release of an old web-based application coded in ASP (classic, using VBScript) and using Microsoft Access. In order to make this application public we need to make a few modifications, not the least of which is moving from Microsoft Access to MySQL. Using Microsoft Access on the back-end [...]]]></description>
			<content:encoded><![CDATA[<p>We recently decided to make a public release of an <em>old</em> web-based application coded in ASP (classic, using VBScript) and using Microsoft Access. In order to make this application public we need to make a few modifications, not the least of which is moving from Microsoft Access to MySQL. Using Microsoft Access on the back-end would significantly hamper the ability of the application to support concurrent users, among other issues.</p>
<p>The majority of the coding modifications have yet to be made, but the database switch has already occurred. In the process of moving from MS Access to MySQL I discovered a few settings that would be helpful should this action need to be performed for other applications. These settings should enable similar applications to be moved with minimal modification to the programming.</p>
<p>First, let&#8217;s review some settings related to the MySQL ODBC driver. The settings are relevant to all versions of the driver, but the name of the setting may be different on different versions (I&#8217;m using 5.1.6). Here are the options which should be selected:</p>
<ul>
<li>Return matched rows instead of affected rows</li>
<li>Treat BIGINT columns as INT columns</li>
<li>Enable safe options</li>
</ul>
<p>The following information relates more generally to changes that may have to be made in the code:</p>
<ul>
<li>MySQL doesn&#8217;t really support server-side cursors so the ODBC drivers fakes it. This is, mostly, fine except that some properties of the Recordset object are not available (namely RecordCount). In order to get full cursor support you should change the location from the server to the client (adUseClient; 3).</li>
<li>ASP doesn&#8217;t understand non-signed integers. This causes problems when performing operations using these values unless you manually type the value in your script, e.g. scriptvar = CInt(objrs(&#8220;dbcol&#8221;)). The other solution is to make all integers signed. Otherwise you will see the error: Variable uses an Automation type not supported in VBScript.</li>
<li>Finally, check your SQL statements for any VBA function calls. These will either have to be modified into MySQL-compatible function calls or removed from the SQL code altogether.</li>
</ul>
<p>There are a number of issues that may be encountered when attempting to convert an ASP-based application from MS Access to MySQL. The issues addressed here are only those relevant to this particular application. Other applications may require additional or different solutions and settings.</p>
<p>Resources:</p>
<ul>
<li><a href="http://www.cynergi.net/exportsql/">MS Access to MySQL migration script</a></li>
<li><a href="http://dev.mysql.com/tech-resources/articles/vb-cursors-and-locks.html">MySQL Developer Zone: MySQL CursorTypes, LockTypes, and CursorLocations</a></li>
<li><a href="http://dev.mysql.com/doc/refman/5.1/en/connector-odbc-configuration.html">MySQL 5.1 Reference Manual: 21.1.4. Connector/ODBC Configuration</a></li>
<li><a href="http://forums.mysql.com/read.php?37,56260">MySQL Forums: type confusion in asp</a></li>
<li><a href="http://lists.mysql.com/mysql/50187">MySQL Lists: Problem with RecordCount with ASP &amp; MySQL </a></li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://techlog.p2061.org/2010/02/26/moving-from-microsoft-access-to-mysql/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Subversion and Third-Party Code</title>
		<link>http://techlog.p2061.org/2009/05/08/subversion-and-third-party-code/</link>
		<comments>http://techlog.p2061.org/2009/05/08/subversion-and-third-party-code/#comments</comments>
		<pubDate>Fri, 08 May 2009 22:28:55 +0000</pubDate>
		<dc:creator>BrianS</dc:creator>
				<category><![CDATA[System Administration]]></category>
		<category><![CDATA[Web Development]]></category>
		<category><![CDATA[subversion]]></category>

		<guid isPermaLink="false">http://techlog.p2061.org/?p=137</guid>
		<description><![CDATA[Often in the course of developing a project it is desirable to use code from a  third party. The main benefit, of course, is being able to add functionality without developing that functionality from scratch. Some third-party projects we have used in the past include FCKEditor (now CKEditor), the Yahoo! User Interface library, and, more [...]]]></description>
			<content:encoded><![CDATA[<p>Often in the course of developing a project it is desirable to use code from a  third party. The main benefit, of course, is being able to add functionality without developing that functionality from scratch. Some third-party projects we have used in the past include FCKEditor (now <a href="http://ckeditor.com/">CKEditor</a>), the <a href="http://developer.yahoo.com/yui/">Yahoo! User Interface library</a>, and, more recently, the <a href="http://cakephp.org/">CakePHP framework</a>.</p>
<p>When our code is maintained in a subversion repository there are two options for including third-party code: <em>externals</em> and <em>vendor branches</em>.<span id="more-137"></span></p>
<p><strong>Externals</strong></p>
<p>For third-party code that will require little modification an externals property definition is preferred. Subversion externals are pointers to subversion sources outside the current path (either within the current repository or that are stored in entirely different repositories). Whenever a copy of our own project is checked out from the repository the third-party code is also checked out. One benefit of this approach is that a local copy of the third-party code does not have to be maintained. If an update to third-party code is available you only need to update the externals reference to the third-party repository.</p>
<p>For example, we want to add an externals definition for FCKEditor to our project. For the sake of this example we&#8217;ll use the 2.6.4-tagged version of FCKEditor and we&#8217;ll link this to the /includes/fckeditor path of our project. The steps are as follows:</p>
<ol>
<li>Ensure that /includes/fckeditor <em>does not exist</em>;</li>
<li>From the root of the working copy of the project run the following command:

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #c20cb9; font-weight: bold;">svn</span> propset <span style="color: #c20cb9; font-weight: bold;">svn</span>:externals <span style="color: #ff0000;">'fckeditor http://svn.fckeditor.net/FCKeditor/tags/2.6.4'</span> includes</pre></div></div>

</li>
<li>Update the local working copy of the project</li>
</ol>
<p>That&#8217;s all there is to it.</p>
<p>When using externals I recommend that we only point to stable (tagged) versions of third-party projects. By pointing to a stable version we can test for bugs and for compatibility between our code and the third-party code prior to implementing updates on our own systems.</p>
<p><strong>Vendor Branches</strong></p>
<p>Vendor branches are locally-maintained copies of third-party code. Vendor branches are treated much like any project developed in-house. Using vendor branches is less desirable mainly due to the extra work required to update the code in the repository when significant additions and deletions have been made by the third-party. However, it is advisable to use a vendor branch when third-party code will require significant modification in order to be useful in own project.</p>
<p>To set up a vendor branch, first create a new project in the subversion repository as described in the post <a href="http://techlog.p2061.org/2008/05/21/using-svn-for-application-deployment/">Using Subversion for Application Development and Deployment</a>. Note that it is standard to place vendor branches in a subdirectory of the &#8220;/vendor&#8221; directory of the repository. Once this is done we can tag stable versions and create branches just as we do with any other project in the repository. To add the vendor branch to another project within our repository I would recommend using an externals link much as we would for any third-party code. This should ease maintenance as the code is updated.</p>
<p>When third-party code is updated there are two methods you can use to update the vendor branch. The first method is best used when there are only a few files added to or removed from the third-party code. In this situation you can manually update a working copy of the trunk with the new release and commit the modifications. Any in-house changes to the code will have to be re-created (either by editing the code again or merging with an older branch).</p>
<p>When a significant number of file changes have been made to the third-party code it&#8217;s easiest to use svn_load_dirs.pl. This file will perform all the operations of adding, removing, and updating the files in the repository. And with the -t option you can automatically create a tagged (stable) version. For example, to update a vendor branch of the Yahoo! UI Library to version 2.6.0 you would issue the following command:</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;">svn_load_dirs.pl <span style="color: #660033;">-t</span> tags<span style="color: #000000; font-weight: bold;">/</span>2.6.0 <span style="color: #c20cb9; font-weight: bold;">svn</span>+<span style="color: #c20cb9; font-weight: bold;">ssh</span>:<span style="color: #000000; font-weight: bold;">//</span>svnrepo<span style="color: #000000; font-weight: bold;">/</span>vendor<span style="color: #000000; font-weight: bold;">/</span>yui trunk <span style="color: #000000; font-weight: bold;">/</span>src<span style="color: #000000; font-weight: bold;">/</span>yui-<span style="color: #000000;">2</span>_6_0</pre></div></div>

<p>There are four parts to this command:</p>
<ul>
<li><code>-t tags/2.6.0</code> : creates a tagged version of the imported code</li>
<li><code>svn+ssh://svnrepo/vendor/yui</code> : the location of the vendor branch</li>
<li><code>trunk</code> : the subdirectory of the vendor branch where the updated code should be imported</li>
<li><code>/src/yui-2_6_0</code> : the path to the updated YUI library code downloaded from the YUI site</li>
</ul>
<p>Once you&#8217;ve executed this command you would continue with modification of the vendor branch just as you would if you had updated it manually.</p>
<p><strong>Wrap-up</strong></p>
<p>Working with both externals and vendor branches should ease the process of integrating third-party code. For more detailed information on these topics see the documentation from the SVN book.</p>
<ul>
<li><a href="http://svnbook.red-bean.com/en/1.2/svn.advanced.externals.html">Version Control with Subversion: Externals Definitions</a></li>
<li><a href="http://svnbook.red-bean.com/en/1.2/svn.advanced.vendorbr.html">Version Control with Subversion: Vendor Branches</a></li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://techlog.p2061.org/2009/05/08/subversion-and-third-party-code/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>CakePHP and CURRENT_TIMESTAMP</title>
		<link>http://techlog.p2061.org/2009/04/17/cakephp-and-current_timestamp/</link>
		<comments>http://techlog.p2061.org/2009/04/17/cakephp-and-current_timestamp/#comments</comments>
		<pubDate>Fri, 17 Apr 2009 20:15:54 +0000</pubDate>
		<dc:creator>BrianS</dc:creator>
				<category><![CDATA[CakePHP]]></category>
		<category><![CDATA[MySQL]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Web Development]]></category>
		<category><![CDATA[bug]]></category>
		<category><![CDATA[cakephp 1.2.1]]></category>

		<guid isPermaLink="false">http://techlog.p2061.org/?p=229</guid>
		<description><![CDATA[As of cakePHP 1.2.1.8004 you can&#8217;t use CURRENT_TIMESTAMP as the default for a column. With MySQL when the default is set to CURRENT_TIMESTAMP the current date+time is inserted for a new row that doesn&#8217;t specifically define the value of the column.
From what I can tell, when CakePHP specifies the values for all columns when it [...]]]></description>
			<content:encoded><![CDATA[<p>As of cakePHP 1.2.1.8004 you can&#8217;t use CURRENT_TIMESTAMP as the default for a column. With MySQL when the default is set to CURRENT_TIMESTAMP the current date+time is inserted for a new row that doesn&#8217;t specifically define the value of the column.</p>
<p>From what I can tell, when CakePHP specifies the values for all columns when it creates a new record. A column with a defined default that is not specifically set by the user is manually set by CakePHP (rather than let MySQL handle defaults upon record insertion). But CakePHP doesn&#8217;t understand the CURRENT_TIMESTAMP keyword and so treats it as a string and wraps it in quotes. This breaks the resulting INSERT statement and you receive an error:</p>
<blockquote><p>Incorrect datetime value: &#8216;CURRENT_TIMESTAMP&#8217;</p></blockquote>
<p>Interestingly, columns that are named &#8220;created&#8221; and &#8220;modified&#8221; receive special handling by CakePHP. These columns are treated like auto-update columns by CakePHP and it sets them as expected. With the special handling of these columns in mind it is possible to get around the CURRENT_TIMESTAMP bug by following the recommended settings for created/modified columns, i.e. specifying the field as DATETIME with a default of NULL. CakePHP will automatically update the columns when inserting/updating records.</p>
<p>References:</p>
<ul>
<li><a href="http://dev.mysql.com/doc/refman/5.0/en/timestamp.html">MySQL Reference Manual: 10.3.1.1. TIMESTAMP Properties</a></li>
<li><a href="http://book.cakephp.org/view/69/created-and-modified">CakePHP Cookbook: 3.7.2.3 created and modified</a></li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://techlog.p2061.org/2009/04/17/cakephp-and-current_timestamp/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Authentication &amp; Authorization with Scaffolding</title>
		<link>http://techlog.p2061.org/2009/04/17/authentication-authorization-with-scaffolding/</link>
		<comments>http://techlog.p2061.org/2009/04/17/authentication-authorization-with-scaffolding/#comments</comments>
		<pubDate>Fri, 17 Apr 2009 18:45:17 +0000</pubDate>
		<dc:creator>BrianS</dc:creator>
				<category><![CDATA[CakePHP]]></category>
		<category><![CDATA[Web Development]]></category>

		<guid isPermaLink="false">http://techlog.p2061.org/?p=220</guid>
		<description><![CDATA[Though scaffolding is not recommended for production sites, I&#8217;ve found it quite handy when just getting started. Unfortunately, it doesn&#8217;t appear that the authentication/authorization (auth^2) mechanism works with scaffolding. You can, however, get auth^2 working manually with just a few lines of code.
First, follow the steps of the Simple Acl controlled Application tutorial from the [...]]]></description>
			<content:encoded><![CDATA[<p>Though scaffolding is not recommended for production sites, I&#8217;ve found it quite handy when just getting started. Unfortunately, it doesn&#8217;t appear that the authentication/authorization (auth^2) mechanism works with scaffolding. You can, however, get auth^2 working manually with just a few lines of code.</p>
<p>First, follow the steps of the <a href="http://book.cakephp.org/view/641/Simple-Acl-controlled-Application">Simple Acl controlled Application tutorial</a> from the CakePHP cookbook up to the section on logging in.</p>
<p>Next, we need to insert the <a href="http://book.cakephp.org/view/645/Acts-As-a-Requester">code that updates the ARO</a> when a user is added or edited. Normally you would place this code in your add/edit action in the users controller, but for scaffolded actions we&#8217;ll use another callback function. Add the following code to your users controller:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">function</span> _afterScaffoldSave<span style="color: #009900;">&#40;</span><span style="color: #000088;">$action</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
  <span style="color: #000088;">$aro</span> <span style="color: #339933;">=&amp;</span>amp<span style="color: #339933;">;</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&amp;</span>gt<span style="color: #339933;">;</span>Acl<span style="color: #339933;">-&amp;</span>gt<span style="color: #339933;">;</span>Aro<span style="color: #339933;">;</span>
  <span style="color: #000088;">$user</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$aro</span><span style="color: #339933;">-&amp;</span>gt<span style="color: #339933;">;</span>findByForeignKeyAndModel<span style="color: #009900;">&#40;</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&amp;</span>gt<span style="color: #339933;">;</span>data<span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'User'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'id'</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'User'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
  <span style="color: #000088;">$group</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$aro</span><span style="color: #339933;">-&amp;</span>gt<span style="color: #339933;">;</span>findByForeignKeyAndModel<span style="color: #009900;">&#40;</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&amp;</span>gt<span style="color: #339933;">;</span>data<span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'User'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'group_id'</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'Group'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
  <span style="color: #000088;">$aro</span><span style="color: #339933;">-&amp;</span>gt<span style="color: #339933;">;</span>id <span style="color: #339933;">=</span> <span style="color: #000088;">$user</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'Aro'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'id'</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
  <span style="color: #000088;">$aro</span><span style="color: #339933;">-&amp;</span>gt<span style="color: #339933;">;</span>save<span style="color: #009900;">&#40;</span><span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'parent_id'</span> <span style="color: #339933;">=&amp;</span>gt<span style="color: #339933;">;</span> <span style="color: #000088;">$group</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'Aro'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'id'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
  <span style="color: #b1b100;">return</span> <span style="color: #009900; font-weight: bold;">TRUE</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>Note: for scaffold callbacks you <strong>must</strong> <code>return TRUE;</code> or the scaffold will not finish building the page.</p>
<p>The above code has been modified from the original in the tutorial, which included a conditional that checked for a change in the user&#8217;s group. As far as I can tell scaffolding causes CakePHP to return only the updated record (even when using the _beforeScaffold method) so you&#8217;re unable to compare the old and new values. As a result you have to update the ARO with every update, even if the user&#8217;s group is not updated.</p>
<p>Finally, for scaffolded actions we need a way to determine if the user is authorized. The AuthComponent has all the functionality we need. Add the following function to any controller using scaffolding that needs auth^2:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">function</span> _beforeScaffold<span style="color: #009900;">&#40;</span><span style="color: #000088;">$action</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
  <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&amp;</span>gt<span style="color: #339933;">;</span>Auth<span style="color: #339933;">-&amp;</span>gt<span style="color: #339933;">;</span>user<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">==</span> <span style="color: #009900; font-weight: bold;">NULL</span> <span style="color: #339933;">&amp;</span>amp<span style="color: #339933;">;&amp;</span>amp<span style="color: #339933;">;</span> <span style="color: #339933;">!</span><span style="color: #990000;">in_array</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'*'</span><span style="color: #339933;">,</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&amp;</span>gt<span style="color: #339933;">;</span>Auth<span style="color: #339933;">-&amp;</span>gt<span style="color: #339933;">;</span>allowedActions<span style="color: #009900;">&#41;</span> <span style="color: #339933;">&amp;</span>amp<span style="color: #339933;">;&amp;</span>amp<span style="color: #339933;">;</span> <span style="color: #339933;">!</span><span style="color: #990000;">in_array</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$action</span><span style="color: #339933;">,</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&amp;</span>gt<span style="color: #339933;">;</span>Auth<span style="color: #339933;">-&amp;</span>gt<span style="color: #339933;">;</span>allowedActions<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
    <span style="color: #000088;">$this</span><span style="color: #339933;">-&amp;</span>gt<span style="color: #339933;">;</span>Session<span style="color: #339933;">-&amp;</span>gt<span style="color: #339933;">;</span>write<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'Auth.redirect'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'/'</span> <span style="color: #339933;">.</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&amp;</span>gt<span style="color: #339933;">;</span>name <span style="color: #339933;">.</span> <span style="color: #0000ff;">'/'</span> <span style="color: #339933;">.</span> <span style="color: #000088;">$action</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #000088;">$this</span><span style="color: #339933;">-&amp;</span>gt<span style="color: #339933;">;</span>Auth<span style="color: #339933;">-&amp;</span>gt<span style="color: #339933;">;</span>loginRedirect <span style="color: #339933;">=</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'controller'</span> <span style="color: #339933;">=&amp;</span>gt<span style="color: #339933;">;</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&amp;</span>gt<span style="color: #339933;">;</span>name<span style="color: #339933;">,</span> <span style="color: #0000ff;">'action'</span> <span style="color: #339933;">=&amp;</span>gt<span style="color: #339933;">;</span> <span style="color: #000088;">$action</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #000088;">$this</span><span style="color: #339933;">-&amp;</span>gt<span style="color: #339933;">;</span>redirect<span style="color: #009900;">&#40;</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&amp;</span>gt<span style="color: #339933;">;</span>Auth<span style="color: #339933;">-&amp;</span>gt<span style="color: #339933;">;</span>loginAction<span style="color: #339933;">,</span> <span style="color: #009900; font-weight: bold;">NULL</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: #b1b100;">return</span> <span style="color: #009900; font-weight: bold;">FALSE</span><span style="color: #339933;">;</span>
  <span style="color: #009900;">&#125;</span> <span style="color: #b1b100;">else</span> <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #339933;">!</span><span style="color: #990000;">in_array</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'*'</span><span style="color: #339933;">,</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&amp;</span>gt<span style="color: #339933;">;</span>Auth<span style="color: #339933;">-&amp;</span>gt<span style="color: #339933;">;</span>allowedActions<span style="color: #009900;">&#41;</span> <span style="color: #339933;">&amp;</span>amp<span style="color: #339933;">;&amp;</span>amp<span style="color: #339933;">;</span> <span style="color: #339933;">!</span><span style="color: #990000;">in_array</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$action</span><span style="color: #339933;">,</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&amp;</span>gt<span style="color: #339933;">;</span>Auth<span style="color: #339933;">-&amp;</span>gt<span style="color: #339933;">;</span>allowedActions<span style="color: #009900;">&#41;</span> <span style="color: #339933;">&amp;</span>amp<span style="color: #339933;">;&amp;</span>amp<span style="color: #339933;">;</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&amp;</span>gt<span style="color: #339933;">;</span>Auth<span style="color: #339933;">-&amp;</span>gt<span style="color: #339933;">;</span>user<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">!==</span> <span style="color: #009900; font-weight: bold;">NULL</span> <span style="color: #339933;">&amp;</span>amp<span style="color: #339933;">;&amp;</span>amp<span style="color: #339933;">;</span> <span style="color: #339933;">!</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&amp;</span>gt<span style="color: #339933;">;</span>Acl<span style="color: #339933;">-&amp;</span>gt<span style="color: #339933;">;</span>check<span style="color: #009900;">&#40;</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&amp;</span>gt<span style="color: #339933;">;</span>Auth<span style="color: #339933;">-&amp;</span>gt<span style="color: #339933;">;</span>user<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&amp;</span>gt<span style="color: #339933;">;</span>Auth<span style="color: #339933;">-&amp;</span>gt<span style="color: #339933;">;</span>action<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
    <span style="color: #000088;">$url</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">'/'</span> <span style="color: #339933;">.</span> <span style="color: #990000;">implode</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'/'</span><span style="color: #339933;">,</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&amp;</span>gt<span style="color: #339933;">;</span>Auth<span style="color: #339933;">-&amp;</span>gt<span style="color: #339933;">;</span>loginAction<span style="color: #009900;">&#41;</span> <span style="color: #339933;">==</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&amp;</span>gt<span style="color: #339933;">;</span>referer<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> ? <span style="color: #0000ff;">'/'</span> <span style="color: #339933;">:</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&amp;</span>gt<span style="color: #339933;">;</span>referer<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #000088;">$this</span><span style="color: #339933;">-&amp;</span>gt<span style="color: #339933;">;</span>Session<span style="color: #339933;">-&amp;</span>gt<span style="color: #339933;">;</span>setFlash<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'You do not have permission to perform that action.'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #000088;">$this</span><span style="color: #339933;">-&amp;</span>gt<span style="color: #339933;">;</span>redirect<span style="color: #009900;">&#40;</span><span style="color: #000088;">$url</span><span style="color: #339933;">,</span> <span style="color: #009900; font-weight: bold;">NULL</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: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>This function checks to see if the user is logged in when accessing restricted actions. If not, the user is redirected to the login page. If so, and if the user is attempting to access a page for which he has no permissions, then the user is bounced back to the referring page.</p>
<p>Of course, you can skip all this if you build a skeleton CRUD using <code>cake bake</code> and specify <em>not</em> to use scaffolding.</p>
]]></content:encoded>
			<wfw:commentRss>http://techlog.p2061.org/2009/04/17/authentication-authorization-with-scaffolding/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Updates for IE8</title>
		<link>http://techlog.p2061.org/2009/02/20/updates-for-ie8/</link>
		<comments>http://techlog.p2061.org/2009/02/20/updates-for-ie8/#comments</comments>
		<pubDate>Fri, 20 Feb 2009 21:00:43 +0000</pubDate>
		<dc:creator>BrianS</dc:creator>
				<category><![CDATA[Web Development]]></category>
		<category><![CDATA[css]]></category>
		<category><![CDATA[ie]]></category>
		<category><![CDATA[javascript]]></category>

		<guid isPermaLink="false">http://techlog.p2061.org/?p=211</guid>
		<description><![CDATA[With the release of IE8 getting closer I took a moment to check out our web site and Benchmarks Online in the new browser. As I suspected, the incompatibilities on our web site were of the same ilk as when IE7 was released and required minor updates. The updates to Benchmarks were also fairly minor, [...]]]></description>
			<content:encoded><![CDATA[<p>With the release of IE8 getting closer I took a moment to check out our web site and <em>Benchmarks Online</em> in the new browser. As I suspected, the incompatibilities on our web site were of the same ilk as when IE7 was released and required minor updates. The updates to <em>Benchmarks</em> were also fairly minor, though did require a bit of effort to track down. Luckily IE8 includes developer tools right in the browser, making debugging web content much easier.</p>
<p>While I was at it, I decided to see how the JS+CSS was working in Safari (latest version on Windows and Mac) and Opera (latest versions on Windows). There were some minor issues with these browsers that I fixed as well. Quickly, Safari and Opera both were having trouble displaying the bullets in my ordered list when the pseudo multi-column-styling was applied. The odd thing is that the numbers were there, just not visible until an element was forced on top of them.</p>
<p>Finally, I decided to update the multi-column list code on the web site to that used in Benchmarks (which is more robust). I did run across one problem in the update that I may have to investigate further. Essentially, the script was not correctly positioning the second+ columns if a margin was specified on the container OL/UL.</p>
]]></content:encoded>
			<wfw:commentRss>http://techlog.p2061.org/2009/02/20/updates-for-ie8/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Excel drops empty columns on CSV export</title>
		<link>http://techlog.p2061.org/2009/02/06/excel-drops-empty-columns-on-csv-export/</link>
		<comments>http://techlog.p2061.org/2009/02/06/excel-drops-empty-columns-on-csv-export/#comments</comments>
		<pubDate>Fri, 06 Feb 2009 21:58:50 +0000</pubDate>
		<dc:creator>BrianS</dc:creator>
				<category><![CDATA[Web Development]]></category>
		<category><![CDATA[bug]]></category>
		<category><![CDATA[excel]]></category>

		<guid isPermaLink="false">http://techlog.p2061.org/?p=174</guid>
		<description><![CDATA[I&#8217;m often tasked with getting data from a flat format (Excel, CSV, etc.) into a database. When the format is Excel  and I have only a few files to work with I find it easiest to export the Excel file to CSV or TSV format. This makes it much easier to script the data conversion [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;m often tasked with getting data from a flat format (Excel, CSV, etc.) into a database. When the format is Excel  and I have only a few files to work with I find it easiest to export the Excel file to CSV or TSV format. This makes it much easier to script the data conversion using PHP. There&#8217;s only one problem, Excel doesn&#8217;t always represent the total number of columns in each row. If there are blank values in the columns at the end of a row in the spreadsheet then the exported data may have fewer value delimeters than expected.</p>
<p>This <a title="Column delimiters are missing in an Excel spreadsheet that is saved as text" href="http://support.microsoft.com/default.aspx?scid=77295">bug has been documented</a> by Microsoft for Excel 2003 and earlier. The solution given by Microsoft is poorly worded, but basically it says to make sure the cells at the end of a row always contain data. Not always a realistic proposition. Luckily I found a <a href="http://www.eggheadcafe.com/aspnet_answers/Excelsetup/Aug2006/post27678998.asp">step-by-step solution</a> that works perfectly:</p>
<p>Put a formula that evaluates to empty (=&#8221;" ) in the last column of  the rows that are empty:</p>
<ol>
<li>select the range in the last column: edit-&gt;goto, click on the &#8220;Special&#8230;&#8221; button, Choose &#8220;Blanks&#8221; and click OK.</li>
<li>type the formula: =&#8221;"</li>
<li>hit ctrl-enter</li>
</ol>
<p>Now when you save the document the appropriate number of delimeters should be present, even in rows with empty cells.</p>
]]></content:encoded>
			<wfw:commentRss>http://techlog.p2061.org/2009/02/06/excel-drops-empty-columns-on-csv-export/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Internet Explorer blocks Firefox downloads</title>
		<link>http://techlog.p2061.org/2009/01/16/internet-explorer-blocks-firefox-downloads/</link>
		<comments>http://techlog.p2061.org/2009/01/16/internet-explorer-blocks-firefox-downloads/#comments</comments>
		<pubDate>Fri, 16 Jan 2009 17:16:34 +0000</pubDate>
		<dc:creator>BrianS</dc:creator>
				<category><![CDATA[Web Development]]></category>
		<category><![CDATA[ie]]></category>
		<category><![CDATA[security]]></category>

		<guid isPermaLink="false">http://techlog.p2061.org/?p=142</guid>
		<description><![CDATA[When designing the school reports I decided to use a GET request on form submission so that it would be easier to bookmark or share a report. I knew at the time that using GET might cause problems down the road, but the utility/programming trade-off seemed worthwhile.
Long URLs
The main problem with GET is that the [...]]]></description>
			<content:encoded><![CDATA[<p>When designing the school reports I decided to use a GET request on form submission so that it would be easier to bookmark or share a report. I knew at the time that using GET might cause problems down the road, but the utility/programming trade-off seemed worthwhile.</p>
<p><strong>Long URLs</strong></p>
<p>The main problem with GET is that the total size a URL is allowed to be (and thus the amount of data passed) is fairly limited when compared to POST. The exact limit varies by browser and web server, but a practical limit is the lowest limit across platforms. In this case that is 2083 characters in Internet Explorer.</p>
<p>Since each report has to pass the list of included packets and items, the URL could easily surpass this limit. Recently one user generated a report that went over the IE limit. Figuring this out, though, proved to be somewhat difficult.</p>
<p><strong>Held up at security</strong></p>
<p>The user in question was using Firefox to access the utility. The report in question was generating and displaying just fine. However, when the user tried to download the report an error would result. It seemed odd that the browser would display the report on screen without issue then error out when attempting to download the same report.</p>
<p>I tried many options, but no matter what I did I was unable to download the report in Firefox. Next I tried the same report in IE and the situation started to clarify. IE would not even display the report. So now I was beginning to think that maybe the GET request was causing problems. Still it was difficult to fathom Firefox displaying the report on screen but refusing to download it.</p>
<p>A little web research finally clarified everything. Firefox attempts to honor the Windows Internet security zone settings for downloaded files. In order to apply the security zone settings Windows has to pass the URL to the IE engine for analysis. Firefox allows URLs of significantly larger size than IE, so the same URL that displays correctly on Firefox will thus cause IE to error out. Since Firefox attempts to honors the security settings, when IE coughs up a hairball due to the URL length the download is aborted.</p>
<p><strong>Solving the problem</strong></p>
<p>Initially I thought to just shorten the request by modifying the variable names on the form. This worked well enough for the problem at hand, but I could easily see having to address the problem again in the future. In the end I decided to modify the code behind the page so that the report parameters are submitted by POST instead of GET. It required more work up front, but will prevent this problem from cropping up in the future.</p>
<p>Plus, the utility has an option to save reports, so bookmarking/sharing is not as much of an issue.</p>
<p><strong>References</strong></p>
<ul>
<li><span id="KonaBody">Boutell.Com: </span><a href="http://www.boutell.com/newfaq/misc/urllength.html">WWW FAQs: What is the maximum length of a URL?</a></li>
<li>Firefox Facts: <a href="http://www.firefoxfacts.com/2008/07/23/security-zone-policy-errors-in-firefox-3/">Security Zone Policy Errors in Firefox 3</a></li>
<li>mozillaZine: <a href="http://kb.mozillazine.org/Unable_to_save_or_download_files#Enable_downloads_blocked_by_Security_Zone_Policy_-_Windows">Unable to save or download files</a></li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://techlog.p2061.org/2009/01/16/internet-explorer-blocks-firefox-downloads/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>CakePHP, Apache, and Ampersands</title>
		<link>http://techlog.p2061.org/2009/01/15/cakephp-apache-and-ampersands/</link>
		<comments>http://techlog.p2061.org/2009/01/15/cakephp-apache-and-ampersands/#comments</comments>
		<pubDate>Thu, 15 Jan 2009 19:44:23 +0000</pubDate>
		<dc:creator>BrianS</dc:creator>
				<category><![CDATA[CakePHP]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Web Development]]></category>

		<guid isPermaLink="false">http://techlog.p2061.org/?p=169</guid>
		<description><![CDATA[I&#8217;m still learning CakePHP. My most recent experimentation is with forms and URL redirecting. In the process I noticed that if the URL includes an ampersand, even in URL-encoded form, CakePHP will read in the URL incorrectly.
In my case, I was taking a form submission and redirecting it to a new page, appending the submitted [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;m still learning CakePHP. My most recent experimentation is with forms and URL redirecting. In the process I noticed that if the URL includes an ampersand, even in URL-encoded form, CakePHP will read in the URL incorrectly.</p>
<p>In my case, I was taking a form submission and redirecting it to a new page, appending the submitted data as URL parameters (e.g. of the form /controller/action/<strong>name:value</strong>). CakePHP handles ampersand in POST-submitted forms just fine, but during the redirect I noticed that the value of the parameter was cut off at the ampersand. For example, I&#8217;m creating a search form for a list of items (located at /items/index). When you submit the form with a value of &#8220;ball &amp; chain&#8221; the controller sees it just fine. The form is submitted to the search action (/items/search) which takes the values, constructs a new URL, and redirects back to the item list (/items/index/Search.keywords:ball+%26+chain). However, the index action only sees &#8220;ball &#8221; &#8230; the rest of the value is assumed to be additional key/value pairs in the querystring.</p>
<p>This problem seems like a pretty major issue to me. A <a title="CakePHP's old bug tracking system is no more, see the original bug report in the Google cache" href="http://74.125.93.132/search?q=cache:HsDTCvwGcI0J:https://trac.cakephp.org/ticket/5751">bug report</a> has already been filed, but I don&#8217;t believe it will be addressed anytime soon. And for good reason, the bug is actually in Apache&#8217;s mod_rewrite module rather than in CakePHP. When mod_rewrite processes a URL it unescapes any escaped characters (newer releases unescape to two levels). What this means for CakePHP is that any escaped characters in the URL become normal characters in the querystring (%26 becomes &amp;).</p>
<p>The best overview of the problem has a good work-around, but it requires modification of the core CakePHP scripts. I&#8217;ll leave that to the experts. On our install I&#8217;ve found that a triple-escaped value will only be unescaped twice, resulting in the proper escaping after being parsed by mod_rewrite.</p>
<p><strong>References<br />
</strong></p>
<ul>
<li><a href="http://www.dracos.co.uk/code/apache-rewrite-problem/">The Apache mod_rewrite Problem</a></li>
<li><a href="http://www.usenet-forums.com/apache-web-server/39839-mod_rewrite-ampersand.html" class="broken_link" >mod_rewrite &amp; ampersand</a></li>
<li><a href="https://issues.apache.org/bugzilla/show_bug.cgi?id=23295">Escape problem in mod_rewrite [P] action&#8230;</a></li>
<li><a href="https://issues.apache.org/bugzilla/show_bug.cgi?id=32328">Make mod_rewrite escaping optional / expose internal map</a></li>
<li><a href="http://drupal.org/node/68886">Handle ampersands in search queries and other URLs when clean URLs are on</a></li>
<li><a href="http://www.mediawiki.org/wiki/Manual:Short_URL/Ampersand_solution">Short URL/Ampersand solution</a></li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://techlog.p2061.org/2009/01/15/cakephp-apache-and-ampersands/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Your float is showing</title>
		<link>http://techlog.p2061.org/2008/11/21/your-float-is-showing/</link>
		<comments>http://techlog.p2061.org/2008/11/21/your-float-is-showing/#comments</comments>
		<pubDate>Fri, 21 Nov 2008 20:27:37 +0000</pubDate>
		<dc:creator>BrianS</dc:creator>
				<category><![CDATA[Web Development]]></category>
		<category><![CDATA[bugs]]></category>
		<category><![CDATA[css]]></category>
		<category><![CDATA[quirks]]></category>
		<category><![CDATA[style]]></category>

		<guid isPermaLink="false">http://techlog.p2061.org/?p=145</guid>
		<description><![CDATA[Float styling is a useful aspect of CSS &#8230; until it&#8217;s not. When a floated element occurs inside a container and you want it to be wholly in that container you have to resort to hacks to do so. Or do you? Never content to assume that a question has been resolved, I decided to [...]]]></description>
			<content:encoded><![CDATA[<p>Float styling is a useful aspect of CSS &#8230; until it&#8217;s not. When a floated element occurs inside a container and you want it to be wholly in that container you have to resort to hacks to do so. Or do you? Never content to assume that a question has been resolved, I decided to see if anyone had come up with a new method of clearing a float. Lo and behold a solution has emerged, and the solution is so simple as to defy logic: apply <code>overflow: auto</code> to the container element. I&#8217;ll leave the full explanation (with examples, alternatives, and warnings) to the experts.</p>
<ul>
<li><a href="http://www.sitepoint.com/blogs/2005/02/26/simple-clearing-of-floats/">SitePoint: Simple Clearing of Floats</a></li>
<li><a href="http://www.quirksmode.org/css/clearing.html">QuirksMode: Clearing Floats</a></li>
<li><a href="http://www.mezzoblue.com/archives/2005/03/03/clearance/">mezzoblue: Clearance</a></li>
</ul>
<p>Of course, there can be advantages to the default float rendering. Most notably I found it useful for creating some nice formatting around blockquotes, such as in our <a href="http://www.project2061.org/publications/textbook/hsbio/report/reports/biology/sfContent.htm">textbook analysis report</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://techlog.p2061.org/2008/11/21/your-float-is-showing/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
