<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/rss2full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><rss 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/" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" version="2.0">

<channel>
	<title>FeedMind</title>
	
	<link>http://www.mind-it.info</link>
	<description>Webtechnology, Architecture and IT Security</description>
	<lastBuildDate>Mon, 09 Aug 2010 21:48:29 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0.1</generator>
		<atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/rss+xml" href="http://feeds.feedburner.com/mind-it/Aqwc" /><feedburner:info uri="mind-it/aqwc" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><item>
		<title>How to connect to Amazon EC2 from Mac OS X with SSH</title>
		<link>http://feedproxy.google.com/~r/mind-it/Aqwc/~3/cD5DtHEFY0I/</link>
		<comments>http://www.mind-it.info/2010/08/06/how-to-connect-to-amazon-ec2-from-mac-os-x/#comments</comments>
		<pubDate>Fri, 06 Aug 2010 20:02:26 +0000</pubDate>
		<dc:creator>postme</dc:creator>
				<category><![CDATA[Featured]]></category>
		<category><![CDATA[Information Security]]></category>
		<category><![CDATA[Webtechnology]]></category>

		<guid isPermaLink="false">http://www.mind-it.info/?p=172</guid>
		<description><![CDATA[Connecting to my Amazon EC2 image (from which this site is running) from Mac Os X took ages to find out and turned out to be relatively simple with the correct information (isn't that always the case). At first I didn't think the builtin Mac OS X ssh could cut it so I started looking into various Mac OS X ssh clients (Fugu, RBrowser, CyberDuck etc ..) but none of those could handle the Amazon public/private key encryption. Then I started looking into using Putty on Mac OS X even though thats not available for Mac OS X (but with a little help from MacPorts). That bombed on problems with GTK1. Dang, what to do?]]></description>
			<content:encoded><![CDATA[<p>Connecting to my Amazon EC2 image (from which this site is running) from Mac Os X took ages to find out and turned out to be relatively simple with the correct information (isn&#8217;t that always the case). At first I didn&#8217;t think the builtin Mac OS X ssh could cut it so I started looking into various Mac OS X ssh clients (Fugu, RBrowser, CyberDuck etc ..) but none of those could handle the Amazon public/private key encryption. Then I started looking into using Putty on Mac OS X even though thats not available for Mac OS X (but with a little help from MacPorts). That bombed on problems with GTK1. Dang, what to do?</p>
<p><span id="more-172"></span></p>
<p>Finally I found the correct information in a <a href="http://www.g-roc.com/29_ssh-vs-putty-private-key-files-ppk-on-mac-os-x.html">blog post</a>, you need to use Puttygen to convert the Amazon .ppk file to OpenSSH format. The OpenSSH format can be used by the Mac OS X (OpenSSH) ssh client. You also need to chmod the direcory where you store the OpenSSH key so it will only allow read access to other users.</p>
<p>After that a simple text file with the following content:</p>
<pre class="brush: bash;">
ssh -2 -i /Users/xxxxx/amazon_ssh.key youruser@yourserver.com
</pre>
<p>And save it in the Desktop area to have it available on your desktop (or save it elsewhere, whatever you like).</p>
<img src="http://feeds.feedburner.com/~r/mind-it/Aqwc/~4/cD5DtHEFY0I" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.mind-it.info/2010/08/06/how-to-connect-to-amazon-ec2-from-mac-os-x/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://www.mind-it.info/2010/08/06/how-to-connect-to-amazon-ec2-from-mac-os-x/</feedburner:origLink></item>
		<item>
		<title>NIST RBAC PHP API package 0.65 released</title>
		<link>http://feedproxy.google.com/~r/mind-it/Aqwc/~3/00MgzU5CBJs/</link>
		<comments>http://www.mind-it.info/2010/06/02/nits-rbac-php-api-package-released/#comments</comments>
		<pubDate>Wed, 02 Jun 2010 20:22:59 +0000</pubDate>
		<dc:creator>postme</dc:creator>
				<category><![CDATA[Featured]]></category>

		<guid isPermaLink="false">http://www.mind-it.info/?p=175</guid>
		<description><![CDATA[I'm happy to release my first public version of the NIST RBAC PHP API library. I've blogged a number of posts on this subject and I hope that the software is of use to you. The package can be downloaded from code.google.com.

The package contains the library, the data model in the form of MySQL DDL instructions, installation documentation and PHPDoc API documentation. It comes with three applications: a management application, a demo application and a test framework. The demo application shows you how to integrate the library with your own application.]]></description>
			<content:encoded><![CDATA[<p>I&#8217;m happy to release my first public version of the NIST RBAC PHP API library. I&#8217;ve blogged a number of posts on this subject and I hope that the software is of use to you. The package can be downloaded from <a title="NIST RBAC PHP API library on code.google.com" href="http://code.google.com/p/nist-rbac/downloads/detail?name=NIST_RBAC_PHP_API_0_65.zip&amp;can=2&amp;q=">code.google.com</a>.</p>
<p>The package contains the library, the data model in the form of MySQL DDL instructions, installation documentation and PHPDoc API documentation. It comes with three applications: a management application, a demo application and a test framework. The demo application shows you how to integrate the library with your own application.</p>
<p><span id="more-175"></span></p>
<p>The code is not OOP, I already had one complaint about that so if you&#8217;re completely hung up on OOP being the only acceptable thing in your life you might want to pass on this one. Then again if you&#8217;re a bit more mature you might still want to take a look and see how much you can salvage for your own project, or decide to take the code and go OOP bezerk on it and improve after your own tastes <img src='http://media.mind-it.info/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> </p>
<p>The library doesn&#8217;t contain any output other than arrays or true/false in accordance with the NIST RBAC formal API description (in <a title="Z notation" href="http://en.wikipedia.org/wiki/Z_notation" target="_blank">Z notation</a>). The management application follows a simple MVC pattern with the controller just passing on requests to the model and the model only respond with arrays or true/false returns. The view is based on a simple XHTML template.</p>
<p>There&#8217;s still a bit of work to do with the session management part of the management application, some sessions tend to hang around and I need to clean up the library code a bit to address this problem. Nothing serious, just annoying (at least in my opinion).</p>
<p>I&#8217;ll do some additional posts in the coming day to clarify the code and its usage. Probably necessary as it is extremely flexible and can therefore be a bit hard to grasp at the start.</p>
<img src="http://feeds.feedburner.com/~r/mind-it/Aqwc/~4/00MgzU5CBJs" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.mind-it.info/2010/06/02/nits-rbac-php-api-package-released/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		<feedburner:origLink>http://www.mind-it.info/2010/06/02/nits-rbac-php-api-package-released/</feedburner:origLink></item>
		<item>
		<title>Language based redirects using mod_rewrite</title>
		<link>http://feedproxy.google.com/~r/mind-it/Aqwc/~3/wAxhs8mVidU/</link>
		<comments>http://www.mind-it.info/2010/02/22/language-based-redirects-using-mod_rewrite/#comments</comments>
		<pubDate>Mon, 22 Feb 2010 16:17:28 +0000</pubDate>
		<dc:creator>postme</dc:creator>
				<category><![CDATA[Webtechnology]]></category>

		<guid isPermaLink="false">http://www.mind-it.info/?p=140</guid>
		<description><![CDATA[For the website of my wife&#8217;s company, www.exportmanagement.nu, I needed a simple approach to direct traffic to the proper pages based on the language preference setting of the visiting browser. It&#8217;s a very simple approach, any browser with Dutch as its language setting will be directed to the main site and any other language will [...]]]></description>
			<content:encoded><![CDATA[<p>For the website of my wife&#8217;s company, <a href="http://www.exportmanagement.nu">www.exportmanagement.nu</a>, I needed a simple approach to direct traffic to the proper pages based on the language preference setting of the visiting browser. It&#8217;s a very simple approach, any browser with Dutch as its language setting will be directed to the main site and any other language will be directed to a smaller, English language based, website. Luckily the swiss army chainsaw named mod_rewrite came to the rescue and the following little code fragment will do just that (placed in an .htaccess file).</p>
<p><span id="more-140"></span> </p>
<pre class="brush: plain;">
RewriteEngine on
RewriteBase /

# All Dutch language browsers redirect to index.html
RewriteCond %{HTTP:Accept-language} ^nl [NC]
RewriteRule ^$ /index.html [L,R=301]

# All non-Dutch browsers redirect to index_en.html
RewriteRule ^$ /index_en.html [L,R=301]
</pre>
<p>The RewriteBase directive makes sure the rewrite rule only triggers when accessing the root of the website, any subsequent request for a specific page will not trigger the rewrite rule.</p>
<img src="http://feeds.feedburner.com/~r/mind-it/Aqwc/~4/wAxhs8mVidU" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.mind-it.info/2010/02/22/language-based-redirects-using-mod_rewrite/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://www.mind-it.info/2010/02/22/language-based-redirects-using-mod_rewrite/</feedburner:origLink></item>
		<item>
		<title>A simple approach to Localization in PHP</title>
		<link>http://feedproxy.google.com/~r/mind-it/Aqwc/~3/O3HXeHTHGBM/</link>
		<comments>http://www.mind-it.info/2010/02/22/a-simple-approach-to-localization-in-php/#comments</comments>
		<pubDate>Mon, 22 Feb 2010 09:31:21 +0000</pubDate>
		<dc:creator>postme</dc:creator>
				<category><![CDATA[PHP]]></category>

		<guid isPermaLink="false">http://www.mind-it.info/?p=133</guid>
		<description><![CDATA[There&#8217;s quite a number of ways to approach localization (L10N) in PHP. Typing in &#8220;simple localization php&#8221; in Google yields an impressive amount of results. I won&#8217;t go into a heavy theoretical approach in what the best way is or that you need to use gettext or any such approach. I just want to present [...]]]></description>
			<content:encoded><![CDATA[<p>There&#8217;s quite a number of ways to approach localization (L10N) in PHP. Typing in &#8220;simple localization php&#8221; in Google yields an impressive amount of results. I won&#8217;t go into a heavy theoretical approach in what the best way is or that you need to use <a href="http://nl2.php.net/manual/en/ref.gettext.php">gettext</a> or any such approach. I just want to present the function(s) I&#8217;m using and leave it up to you to decide whether you like the approach.</p>
<p><span id="more-133"></span></p>
<p>First some constants that I use. You can rip them out if you don&#8217;t like them, they&#8217;re not essential, I just like using constants for this type of work.</p>
<pre class="brush: php;">
/**
* Define the url path for the resources
*/
defined('INCLUDE_PATH') or define('INCLUDE_PATH', '/include');

/**
* Define the language using language code based on BCP 47 + RFC 4644,
* http://www.rfc-editor.org/rfc/bcp/bcp47.txt
*
* The language files can be found in directory 'lang'
*/
defined('LANGUAGE') or define('LANGUAGE', 'en-us');
</pre>
<p>The constants are used in the code below, replace them with your own values or approach where necessary. What happens is that a language file is loaded based on the configured language. A static array $translations is used to ensure that the language file is loaded once and every other subsequent call is handled through the $translations array in memory rather than reloading the language file. The language file is constructed in JSON format and when the language file is loaded into the $translations array the PHP <a href="http://php.net/manual/en/function.json-decode.php">json_decode</a> function is used to convert from JSON to PHP associative array format. When a call is made to the function a language phrase is passed to the function and the matching value is found in the $translations array by using the language phrase as a key for the associative array.</p>
<p><!--more--></p>
<pre class="brush: php;">
/**
* Load the proper language file and return the translated phrase
*
* The language file is JSON encoded and returns an associative array
* Language filename is determined by BCP 47 + RFC 4646
* http://www.rfc-editor.org/rfc/bcp/bcp47.txt
*
* @param string $phrase The phrase that needs to be translated
* @return string
*/
function localize($phrase) {
    /* Static keyword is used to ensure the file is loaded only once */
    static $translations = NULL;
    /* If no instance of $translations has occured load the language file */
    if (is_null($translations)) {
        $lang_file = INCLUDE_FILE . '/lang/' . LANGUAGE . '.txt';
        if (!file_exists($lang_file)) {
            $lang_file = INCLUDE_FILE . '/lang/' . 'en-us.txt';
        }
        $lang_file_content = file_get_contents($lang_file);
        /* Load the language file as a JSON object and transform it into an associative array */
        $translations = json_decode($lang_file_content, true);
    }
    return $translations[$phrase];
}
</pre>
<p>An excerpt of the US English language file (in JSON format):</p>
<pre class="brush: jscript;">
{
    &quot;lang&quot;:&quot;en-us&quot;,
    &quot;No&quot;:&quot;No&quot;,
    &quot;Yes&quot;:&quot;Yes&quot;,
    &quot;or&quot;:&quot;or&quot;,
    &quot;Do you require help&quot;:&quot;Do you require help&quot;
}
</pre>
<p>An excerpt of the German language file:</p>
<pre class="brush: jscript;">
{
    &quot;lang&quot;:&quot;de&quot;,
    &quot;No&quot;:&quot;Nein&quot;,
    &quot;Yes&quot;:&quot;Ja&quot;,
    &quot;or&quot;:&quot;oder&quot;,
    &quot;Do you require help&quot;:&quot;Brauchen Sie Hilfe&quot;
}
</pre>
<p>An example of it&#8217;s usage:</p>
<pre class="brush: php;">
print localize('Do you require help') . localize('Yes') . localize('or') . localize('No');
</pre>
<p>An example of usage in some of my own code:</p>
<pre class="brush: php;">
$create_page_array = array(
    'status_message' =&gt; $status_message,
    'table_caption' =&gt; localize('Delete Operation'),
    'table_explanation' =&gt; localize('This command deletes an operation'),
    'table_content' =&gt; $table_content,
    'checkbox' =&gt; 'operation_name',
    'table_sort' =&gt; '[[1,0]]'
);
</pre>
<p>The advantages to me are:</p>
<ol>
<li>Very easy integration into your code</li>
<li>The language phrases remain recognizable in your own code</li>
<li>The language files can be easily customised because the original phrase is part of the translation</li>
<li>Language file needs to be loaded only once</li>
<li>The language file is coded in an open standard (JSON) and can be processed in other ways that you currently don&#8217;t foresee</li>
</ol>
<img src="http://feeds.feedburner.com/~r/mind-it/Aqwc/~4/O3HXeHTHGBM" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.mind-it.info/2010/02/22/a-simple-approach-to-localization-in-php/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		<feedburner:origLink>http://www.mind-it.info/2010/02/22/a-simple-approach-to-localization-in-php/</feedburner:origLink></item>
		<item>
		<title>A Simple Front End Controller in PHP</title>
		<link>http://feedproxy.google.com/~r/mind-it/Aqwc/~3/Aoky-CPlQpY/</link>
		<comments>http://www.mind-it.info/2010/01/18/a-simple-front-end-controller-in-php/#comments</comments>
		<pubDate>Mon, 18 Jan 2010 09:21:36 +0000</pubDate>
		<dc:creator>Meint Post</dc:creator>
				<category><![CDATA[Featured]]></category>
		<category><![CDATA[Information Security]]></category>
		<category><![CDATA[PHP]]></category>

		<guid isPermaLink="false">http://www.mind-it.info/?p=82</guid>
		<description><![CDATA[A Front End Controller is part of an MVC pattern. The controller receives input and initiates a response by making calls on model objects. An MVC application may be a collection of model/view/controller triplets, each responsible for a different UI element. MVC is often seen in web applications where the view is the HTML or [...]]]></description>
			<content:encoded><![CDATA[<p>A Front End Controller is part of an <a href="http://en.wikipedia.org/wiki/Model%E2%80%93view%E2%80%93controller">MVC pattern</a>.</p>
<blockquote cite="http://en.wikipedia.org/wiki/Model%E2%80%93view%E2%80%93controller"><p>The controller receives input and initiates a response by making calls on model objects. An MVC application may be a collection of model/view/controller triplets, each responsible for a different UI element. MVC is often seen in web applications where the view is the HTML or XHTML generated by the app. The controller receives GET or POST input and decides what to do with it, handing over to domain objects (i.e. the model) that contain the business rules and know how to carry out specific tasks such as processing a new subscription.</p></blockquote>
<p><span id="more-82"></span><br />
People tend to think up very complex solutions for Front End Controllers in PHP. However the only thing a Front End Controller needs to do is act as a switchboard between view and model. It is also the part of the application that is most prone to attacks as you can manipulate URL&#8217;s and thereby attack or subvert the controller logic in giving you access to functions you&#8217;re not entitled to. For my NIST RBAC API PHP implementation I have made a simple and secure controller that I want to share. Code follows below:</p>
<p>If no action has been set the Default action will be called</p>
<pre class="brush: php;">$url_action = (empty($_REQUEST['action'])) ? 'Default' : $_REQUEST['action'];</pre>
<p>Filter the GET/POST action parameter to allow only alphabetic characters because this is a main entry point to the program logic and therefore an interesting target for URL manipulation</p>
<pre class="brush: php;">
if (!ctype_alpha($url_action)) {
    trigger_error('Action string has been tampered with, request terminated', E_USER_ERROR);
}
</pre>
<p>Check whether the action is set (it should be because it is filled with a default value anyway), then check whether the function exists by calling it and then call the function on behalf of the controller. Any error conditions are raised through trigger_error and the execution stops.</p>
<pre class="brush: php;">
if (isset($url_action)) {
    if (is_callable($url_action)) {
        call_user_func($url_action);
    } else {
        trigger_error('Function does not exist, request terminated', E_USER_ERROR);
    }
} else {
    trigger_error('Function does not exist, request terminated', E_USER_ERROR);
}
</pre>
<p>End of the Front End Controller code. Subsequent code consists of view functions.</p>
<p>Complete code:</p>
<pre class="brush: php;">
$url_action = (empty($_REQUEST['action'])) ? 'Default' : $_REQUEST['action'];
if (!ctype_alpha($url_action)) {
    trigger_error('Action string has been tampered with, request terminated', E_USER_ERROR);
}
if (isset($url_action)) {
    if (is_callable($url_action)) {
        call_user_func($url_action);
    } else {
        trigger_error('Function does not exist, request terminated', E_USER_ERROR);
    }
} else {
    trigger_error('Function does not exist, request terminated', E_USER_ERROR);
}
</pre>
<p>The controller checks whether the url_action consists of alphabetic characters, if so whether the function that is called exists and if the function exists it calls the function on behalf of the request. The function itself needs to check whether the user is entitled to accessing the function. This can be done through the NIST RBAC PHP API of which I will post later.</p>
<p>The names of the action need to be reflected in the function names, i.e. an ?action=AddUser will direct the user to function AddUser(). If this is undesirable you need to add a mapping table like:</p>
<pre class="brush: php;">
$url_mapping = array('UrlAction' =&gt; 'NameoftheFunction' ...);
</pre>
<p>And you can then loop through that array and match up the url action with the proper function name.</p>
<img src="http://feeds.feedburner.com/~r/mind-it/Aqwc/~4/Aoky-CPlQpY" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.mind-it.info/2010/01/18/a-simple-front-end-controller-in-php/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		<feedburner:origLink>http://www.mind-it.info/2010/01/18/a-simple-front-end-controller-in-php/</feedburner:origLink></item>
		<item>
		<title>NIST RBAC Data Model</title>
		<link>http://feedproxy.google.com/~r/mind-it/Aqwc/~3/kTKC_1p2PJ4/</link>
		<comments>http://www.mind-it.info/2010/01/09/nist-rbac-data-model/#comments</comments>
		<pubDate>Sat, 09 Jan 2010 13:50:59 +0000</pubDate>
		<dc:creator>Meint Post</dc:creator>
				<category><![CDATA[Featured]]></category>
		<category><![CDATA[Information Security]]></category>
		<category><![CDATA[PHP]]></category>

		<guid isPermaLink="false">http://www.mind-it.info/?p=58</guid>
		<description><![CDATA[I&#8217;m nearing the end of my development work for the first version of the NIST RBAC API for PHP. Rather than trying to explain this myself I quote the Wikipedia page on this and Role Based Access Control (RBAC) in general: The NIST RBAC model is a standardized definition of role based access control. Although [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;m nearing the end of my development work for the first version of the <a href="http://www.nist.gov/cgi-bin/exit_nist.cgi?url=http://www.techstreet.com/cgi-bin/detail?product_id=1151353">NIST RBAC</a> API for PHP. Rather than trying to explain this myself I quote the <a href="http://en.wikipedia.org/wiki/NIST_RBAC_model">Wikipedia</a> page on this and Role Based Access Control (RBAC) in general:<br />
<span id="more-58"></span></p>
<blockquote><p>The NIST RBAC model is a standardized definition of role based access control. Although originally developed by the National Institute of Standards and Technology, the standard was adopted and is copyrighted and distributed as INCITS 359-2004 by the International Committee for Information Technology Standards (INCITS).</p>
<p>In computer systems security, role-based access control (RBAC)[1][2] is an approach to restricting system access to authorized users. It is a newer alternative approach to mandatory access control (MAC) and discretionary access control (DAC). RBAC is sometimes referred to as role-based security.</p>
<p>Within an organization, roles are created for various job functions. The permissions to perform certain operations are assigned to specific roles. Members of staff (or other system users) are assigned particular roles, and through those role assignments acquire the permissions to perform particular system functions. Unlike context-based access control (CBAC), RBAC does not look at the message context (such as a connection&#8217;s source).</p>
<p>Since users are not assigned permissions directly, but only acquire them through their role (or roles), management of individual user rights becomes a matter of simply assigning appropriate roles to the user; this simplifies common operations, such as adding a user, or changing a user&#8217;s department.</p></blockquote>
<p>The NIST RBAC Model uses a limited set of concepts to define an RBAC system as depicted below. The system has <strong>(1) users</strong>, users have <strong>(2) sessions</strong> and sessions and users have <strong>(3) roles</strong> assigned to them. Each role consist of <strong>(4) permissions</strong> and permissions are based on <strong>(5) objects</strong> and <strong>(6) operations</strong>.</p>
<p><a rel="attachment wp-att-187" href="http://www.mind-it.info/2010/01/09/nist-rbac-data-model/nist_rbac-2/"><img class="alignnone size-medium wp-image-187" title="NIST RBAC model" src="http://media.mind-it.info/wp-content/uploads/2010/01/nist_rbac-300x122.png" alt="" width="300" height="122" /></a></p>
<p>Great though standards are they hardly ever give you concrete stuff like an actual implementation or a data model. As part of my series of little releases leading up to the release of the NIST RBAC PHP API I&#8217;m delivering a worked out RBAC Data Model based on the NIST standard. The model has been designed with an ERD tool named &#8220;<a href="http://www.datanamic.com/dezign/">Dezign for Databases</a>&#8221; and it can generate the DDL code for just about any database. For the moment I&#8217;m releasing this in MySQL 5 format but if there are requests for other databases please let me know and I&#8217;ll update the post accordingly.</p>
<p>An Entity-Relationship diagram of the model is depicted below:<br />
<a rel="attachment wp-att-195" href="http://www.mind-it.info/2010/01/09/nist-rbac-data-model/rbac_model/"><img class="alignnone size-medium wp-image-195" title="NIST RBAC Model" src="http://media.mind-it.info/wp-content/uploads/2010/01/rbac_model-300x177.png" alt="" width="300" height="177" /></a></p>
<p>The model contains 6 main entities:</p>
<ol>
<li>user: this contains all the user data</li>
<li>session: this contains the session data for all currently logged on users</li>
<li>role: this contains all the roles that are defined</li>
<li>permissions: this contains all the permissions based on objects and operations</li>
<li>object: objects are the items that require protection</li>
<li>operation: operations are the actions that are performed on the objects</li>
</ol>
<p>As you can see the entities in the data model map on the entities shown in the NIST RBAC entity model. Because there are a fair number of many-to-many relationships in the model there are a number of bridge tables to help out:</p>
<ol>
<li><del datetime="2010-07-30T15:47:20+00:00">user_session: this combines the user with an active session, i.e. which users of the set of all users are currently logged in</del> As Alex pointed out in the comments below this is not a many-to-many relationship but a one-to-many relationship and therefore doens&#8217;t require a bridge table</li>
<li>user_role: this combines the user with any number of roles (but at least one)</li>
<li>session_role: when a user logs in all the assigned roles are associated with the session. This allows for temporary changes to the role structure, i.e. take away a role for the duration of the session or add a role for the duration of the session</li>
<li>role_permission: this associates a role with one or more permissions</li>
</ol>
<p>The model is 4NF/5NF and fully relational. For MySQL usage it requires an InnoDB (or equivalent) database. I have only tested it myself with MySQL 5.0/5.1 and the InnoDB storage engine but there should be nothing in the DDL file that would conflict with other (transactional) storage engines. If you encounter problems with executing the file please let me know (don&#8217;t know if I can fix them but I&#8217;ll give it a try).</p>
<p>You can execute the code below as a SQL query, either directly in MySQL command line or via phpMyAdmin. Don&#8217;t forget to create a database, and select that database, before you execute the query!</p>
<pre class="brush: sql;">
# ---------------------------------------------------------------------- #
# Script generated with: DeZign for Databases v6.1.2                     #
# Target DBMS:           MySQL 5                                         #
# Project file:          rbac_nist_0_17.dez                              #
# Project name:          nist rbac model                                 #
# Author:                m.e. post                                       #
# Script type:           Database creation script                        #
# Created on:            2010-07-31 20:26                                #
# ---------------------------------------------------------------------- #

# ---------------------------------------------------------------------- #
# Tables                                                                 #
# ---------------------------------------------------------------------- #

# ---------------------------------------------------------------------- #
# Add table &quot;user&quot;                                                       #
# ---------------------------------------------------------------------- #

CREATE TABLE `user` (
 `user_id` INTEGER(8) NOT NULL AUTO_INCREMENT,
 `username` VARCHAR(40) NOT NULL,
 `password` VARCHAR(64) NOT NULL,
 `nonce` TIMESTAMP NOT NULL DEFAULT '0000-00-00 00:00:00',
 `first_name` VARCHAR(50) NOT NULL,
 `family_name` VARCHAR(100) NOT NULL,
 `email` VARCHAR(100) NOT NULL,
 PRIMARY KEY (`user_id`)
)
 ENGINE=InnoDB  DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci AUTO_INCREMENT=1 ;

# ---------------------------------------------------------------------- #
# Add table &quot;role&quot;                                                       #
# ---------------------------------------------------------------------- #

CREATE TABLE `role` (
 `role_id` INTEGER(8) NOT NULL AUTO_INCREMENT,
 `name` VARCHAR(100) NOT NULL,
 PRIMARY KEY (`role_id`)
)
 ENGINE=InnoDB  DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci AUTO_INCREMENT=1 ;

# ---------------------------------------------------------------------- #
# Add table &quot;user_role&quot;                                                  #
# ---------------------------------------------------------------------- #

CREATE TABLE `user_role` (
 `user_id` INTEGER(8) NOT NULL,
 `role_id` INTEGER(8) NOT NULL,
 PRIMARY KEY (`user_id`, `role_id`)
)
 ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;

CREATE INDEX `IDX_user_role_1` ON `user_role` (`user_id`);

CREATE INDEX `IDX_user_role_2` ON `user_role` (`role_id`);

# ---------------------------------------------------------------------- #
# Add table &quot;session&quot;                                                    #
# ---------------------------------------------------------------------- #

CREATE TABLE `session` (
 `session_id` INTEGER(8) NOT NULL AUTO_INCREMENT,
 `user_id` INTEGER(8) NOT NULL,
 `name` VARCHAR(64) NOT NULL,
 `created` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
 PRIMARY KEY (`session_id`, `user_id`)
)
 ENGINE=InnoDB  DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci AUTO_INCREMENT=1 ;

# ---------------------------------------------------------------------- #
# Add table &quot;operation&quot;                                                  #
# ---------------------------------------------------------------------- #

CREATE TABLE `operation` (
 `operation_id` INTEGER(2) NOT NULL AUTO_INCREMENT,
 `name` VARCHAR(100) NOT NULL,
 `_create` TINYINT(1) DEFAULT NULL,
 `_read` TINYINT(1) DEFAULT NULL,
 `_update` TINYINT(1) DEFAULT NULL,
 `_delete` TINYINT(1) DEFAULT NULL,
 `locked` TINYINT(1) NOT NULL DEFAULT 0,
 PRIMARY KEY (`operation_id`)
)
 ENGINE=InnoDB  DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci AUTO_INCREMENT=1 ;

# ---------------------------------------------------------------------- #
# Add table &quot;object&quot;                                                     #
# ---------------------------------------------------------------------- #

CREATE TABLE `object` (
 `object_id` INTEGER(8) NOT NULL AUTO_INCREMENT,
 `name` VARCHAR(100) NOT NULL,
 `locked` TINYINT(1) NOT NULL DEFAULT 0,
 PRIMARY KEY (`object_id`)
)
 ENGINE=InnoDB  DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci AUTO_INCREMENT=1 ;

# ---------------------------------------------------------------------- #
# Add table &quot;permission&quot;                                                 #
# ---------------------------------------------------------------------- #

CREATE TABLE `permission` (
 `permission_id` INTEGER(8) NOT NULL AUTO_INCREMENT,
 `name` VARCHAR(100) NOT NULL,
 `object_id` INTEGER(8) NOT NULL,
 `operation_id` INTEGER(2) NOT NULL,
 PRIMARY KEY (`permission_id`, `name`, `object_id`, `operation_id`)
)
 ENGINE=InnoDB  DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci AUTO_INCREMENT=1 ;

CREATE INDEX `IDX_permission_1` ON `permission` (`object_id`);

CREATE INDEX `IDX_permission_2` ON `permission` (`operation_id`);

# ---------------------------------------------------------------------- #
# Add table &quot;role_permission&quot;                                            #
# ---------------------------------------------------------------------- #

CREATE TABLE `role_permission` (
 `role_id` INTEGER(8) NOT NULL,
 `permission_id` INTEGER(8) NOT NULL,
 PRIMARY KEY (`role_id`, `permission_id`)
)
 ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;

CREATE INDEX `IDX_role_permission_1` ON `role_permission` (`role_id`);

CREATE INDEX `IDX_role_permission_2` ON `role_permission` (`permission_id`);

# ---------------------------------------------------------------------- #
# Add table &quot;session_role&quot;                                               #
# ---------------------------------------------------------------------- #

CREATE TABLE `session_role` (
 `role_id` INTEGER(8) NOT NULL,
 `session_id` INTEGER(8) NOT NULL,
 `user_id` INTEGER(8) NOT NULL,
 PRIMARY KEY (`role_id`, `session_id`, `user_id`)
)
 ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;

CREATE INDEX `IDX_session_role_1` ON `session_role` (`role_id`);

CREATE INDEX `IDX_session_role_2` ON `session_role` (`session_id`);

# ---------------------------------------------------------------------- #
# Foreign key constraints                                                #
# ---------------------------------------------------------------------- #

ALTER TABLE `user_role` ADD CONSTRAINT `user_user_role`
 FOREIGN KEY (`user_id`) REFERENCES `user` (`user_id`) ON DELETE CASCADE ON UPDATE CASCADE;

ALTER TABLE `user_role` ADD CONSTRAINT `role_user_role`
 FOREIGN KEY (`role_id`) REFERENCES `role` (`role_id`) ON DELETE CASCADE ON UPDATE CASCADE;

ALTER TABLE `session` ADD CONSTRAINT `user_session`
 FOREIGN KEY (`user_id`) REFERENCES `user` (`user_id`) ON DELETE CASCADE ON UPDATE CASCADE;

ALTER TABLE `permission` ADD CONSTRAINT `object_permission`
 FOREIGN KEY (`object_id`) REFERENCES `object` (`object_id`) ON DELETE CASCADE ON UPDATE CASCADE;

ALTER TABLE `permission` ADD CONSTRAINT `operation_permission`
 FOREIGN KEY (`operation_id`) REFERENCES `operation` (`operation_id`) ON DELETE CASCADE ON UPDATE CASCADE;

ALTER TABLE `role_permission` ADD CONSTRAINT `role_role_permission`
 FOREIGN KEY (`role_id`) REFERENCES `role` (`role_id`) ON DELETE CASCADE ON UPDATE CASCADE;

ALTER TABLE `role_permission` ADD CONSTRAINT `permission_role_permission`
 FOREIGN KEY (`permission_id`) REFERENCES `permission` (`permission_id`) ON DELETE CASCADE ON UPDATE CASCADE;

ALTER TABLE `session_role` ADD CONSTRAINT `role_session_role`
 FOREIGN KEY (`role_id`) REFERENCES `role` (`role_id`) ON DELETE CASCADE ON UPDATE CASCADE;

ALTER TABLE `session_role` ADD CONSTRAINT `session_session_role`
 FOREIGN KEY (`session_id`, `user_id`) REFERENCES `session` (`session_id`,`user_id`) ON DELETE CASCADE ON UPDATE CASCADE;
</pre>
<img src="http://feeds.feedburner.com/~r/mind-it/Aqwc/~4/kTKC_1p2PJ4" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.mind-it.info/2010/01/09/nist-rbac-data-model/feed/</wfw:commentRss>
		<slash:comments>9</slash:comments>
		<feedburner:origLink>http://www.mind-it.info/2010/01/09/nist-rbac-data-model/</feedburner:origLink></item>
		<item>
		<title>Serving media files from a different url with Django and NGINX</title>
		<link>http://feedproxy.google.com/~r/mind-it/Aqwc/~3/v3jO_05gK7c/</link>
		<comments>http://www.mind-it.info/2009/11/21/serving-media-files-from-a-different-url-with-django-and-nginx/#comments</comments>
		<pubDate>Sat, 21 Nov 2009 07:04:36 +0000</pubDate>
		<dc:creator>Meint Post</dc:creator>
				<category><![CDATA[Featured]]></category>
		<category><![CDATA[Webtechnology]]></category>

		<guid isPermaLink="false">http://www.mind-it.info/?p=49</guid>
		<description><![CDATA[Media files in Django are served through the web server and they can be served with a different url than the Django content itself. By spreading requests across multiple urls you can speed up your site because the browser will execute requests in parallel. The rule of thumb seems to be a maximum of 2-3 [...]]]></description>
			<content:encoded><![CDATA[<p>Media files in Django are served through the web server and they can be served with a different url than the Django content itself. By spreading requests across multiple urls you can speed up your site because the browser will execute requests in parallel. The rule of thumb seems to be a maximum of 2-3 hostnames otherwise the added DNS requests negate the speed up effect.<br />
<span id="more-49"></span><br />
In settings.py:</p>
<pre class="brush: python;">MEDIA_URL = 'media.example.com'</pre>
<p>In NGINX:</p>
<pre class="brush: cpp;">
server {
  listen 80;
  server_name media.example.com;
  location {
    root /PATH/TO/MEDIA/FILES;
  }
}
</pre>
<p>That&#8217;s it, very easy. Oh please replace the media.example.com with your own URL of course.</p>
<img src="http://feeds.feedburner.com/~r/mind-it/Aqwc/~4/v3jO_05gK7c" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.mind-it.info/2009/11/21/serving-media-files-from-a-different-url-with-django-and-nginx/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://www.mind-it.info/2009/11/21/serving-media-files-from-a-different-url-with-django-and-nginx/</feedburner:origLink></item>
		<item>
		<title>Logging out of a Basic Authentication session (with PHP example)</title>
		<link>http://feedproxy.google.com/~r/mind-it/Aqwc/~3/Sb1cYAiNEeo/</link>
		<comments>http://www.mind-it.info/2009/10/04/logging-out-of-a-basic-authentication-session-with-php-example/#comments</comments>
		<pubDate>Sun, 04 Oct 2009 06:44:11 +0000</pubDate>
		<dc:creator>Meint Post</dc:creator>
				<category><![CDATA[Featured]]></category>
		<category><![CDATA[Information Security]]></category>
		<category><![CDATA[PHP]]></category>

		<guid isPermaLink="false">http://www.mind-it.info/?p=32</guid>
		<description><![CDATA[A good friend of mine asked if it was possible to log out of a Basic Authentication session. My first knee-jerk response was that Basic Authentication has no log out function and you should close the browser to safely log out of the session. After some days silence he came back with a script he&#8217;d [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.kidsvolgsysteem.nl/">A good friend of mine</a> asked if it was possible to log out of a Basic Authentication session. My first knee-jerk response was that Basic Authentication has no log out function and you should close the browser to safely log out of the session. After some days silence he came back with a script he&#8217;d found on the php.net site. The script used sessions to break the Basic Authentication behavior of the browser. It wasn&#8217;t a very successful script because it only worked in a limited set of browsers but it got me thinking about a better solution.</p>
<p><span id="more-32"></span> </p>
<p>The best place to start with these challenges is to read the appropriate standard to learn what the original implementers had in mind with their solution. The standard for Basic Authentication is <a href="http://www.ietf.org/rfc/rfc2617.txt">RFC 2617</a>. The standard states:</p>
<blockquote><p>The realm directive (case-insensitive) is required for all authentication schemes that issue a challenge. The realm value (case-sensitive), in combination with the canonical root URL (the absoluteURI for the server whose abs_path is empty; see section 5.1.2 of [2]) of the server being accessed, defines the protection space.</p></blockquote>
<p>So there&#8217;s two items that define the Basic Authentication protection space:</p>
<ul>
<li>realm: a server provided, unique string identifier</li>
<li>abs_path: the url</li>
</ul>
<p>By making both items unique and changing them at log out time you basically break the basic authentication protection space and effectively log out the user.</p>
<p>The solution requires the use of mod_rewrite to direct traffic for non-existent resources to the index.php file. Please place a .htaccess file with the following contents in the folder that you wish to protect:</p>
<p>.htaccess:</p>
<pre class="brush: cpp;">
RewriteEngine On
RewriteCond %{REQUEST_URI} !^$
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . index.php [NC,L]
</pre>
<p>Place an index.php file in the same folder (/auth in this example) with the following content:</p>
<pre class="brush: php;">
&lt;?php

session_start();

if (empty($_SESSION['session_id'])) {
    session_regenerate_id();
    $_SESSION['session_id'] = session_id();
    header(&quot;Location: /auth/&quot; . $_SESSION['session_id'] . &quot;/&quot;, TRUE, 301);
}

$url_action = (empty($_REQUEST['action'])) ? 'HomePage' : $_REQUEST['action'];
if (isset($url_action)) {
    if (is_callable($url_action)) {
        call_user_func($url_action);
    } else {
        print 'Function does not exist, request terminated';
    }
}

function HomePage() {
    print '&lt;h1&gt;Homepage&lt;/h1&gt;';
    print '&lt;p&gt;&lt;a href=&quot;?action=LogIn&quot;&gt;LogIn&lt;/a&gt;&lt;/p&gt;;
    print '&lt;p&gt;&lt;a href=&quot;?action=LogOut&quot;&gt;LogOut&lt;/a&gt;&lt;/p&gt;';
    print '&lt;p&gt;&lt;a href=&quot;?action=SecureContent&quot;&gt;Secure Content&lt;/a&gt;&lt;/p&gt;';
}

function LogIn($url='') {
    $session_id = $_SESSION['session_id'];
    while (!IsAuthenticated()) {
        header('WWW-Authenticate: Basic realm=&quot;' . $session_id . '&quot;');
        header('HTTP/1.1 401 Unauthorized');
        die('Authorization Required');
    }
    if (!empty($url)) {
        return TRUE;
    } else {
        header(&quot;Location: /auth/&quot; . $_SESSION['session_id'] . &quot;/&quot;, TRUE, 301);
    }
}	

function LogOut() {
    session_destroy();
    session_unset($_SESSION['session_id']);
    header(&quot;Location: /auth/&quot;, TRUE, 301);
}

function SecureContent() {
    if (LogIn(&quot;SecureContent&quot;)) {
        print '&lt;h1&gt;Secure Content&lt;/h1&gt;';
        print '&lt;p&gt;This is secure content&lt;/p&gt;';
        print '&lt;p&gt;&lt;a href=&quot;/auth/' . $_SESSION['session_id'] . '/?action=HomePage&quot;&gt;Home Page&lt;/a&gt;&lt;/p&gt;';
    } else {
        print '&lt;h1&gt;Not Authorized&lt;/h1&gt;';
    }
}

function IsAuthenticated() {
    if (isset($_SERVER['PHP_AUTH_USER']) &amp;&amp; isset($_SERVER['PHP_AUTH_PW'])) {
        $httpd_username = filter_var($_SERVER['PHP_AUTH_USER'], FILTER_SANITIZE_STRING, FILTER_FLAG_ENCODE_HIGH|FILTER_FLAG_ENCODE_LOW);
        $httpd_password = filter_var($_SERVER['PHP_AUTH_PW'], FILTER_SANITIZE_STRING, FILTER_FLAG_ENCODE_HIGH|FILTER_FLAG_ENCODE_LOW);
        if ($httpd_username == &quot;test&quot; &amp;&amp; $httpd_password == &quot;test&quot;) {
            return TRUE;
        } else {
            return FALSE;
        }
    }
    return FALSE;
}

?&gt;
</pre>
<p>Both files need to be put in a folder named /auth for these examples to work. You can change the folder name in the index.php example to suit your own environment.</p>
<p>A the start of the script a unique id is generated through PHP session mechanism and this session id is inserted into the url (hence the requirement for mod_rewrite to catch these urls). A redirect takes place to this new url and the homepage is shown. If you click on login a 401 header is generated using a realm that uses the same session id. If you click logout the current session id is destroyed and you are redirected to the start of the script where a new session id is generated. If you click on a protected item without a login the login function is called.</p>
<img src="http://feeds.feedburner.com/~r/mind-it/Aqwc/~4/Sb1cYAiNEeo" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.mind-it.info/2009/10/04/logging-out-of-a-basic-authentication-session-with-php-example/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://www.mind-it.info/2009/10/04/logging-out-of-a-basic-authentication-session-with-php-example/</feedburner:origLink></item>
		<item>
		<title>Switching to WordPress</title>
		<link>http://feedproxy.google.com/~r/mind-it/Aqwc/~3/DSF0O0477Zw/</link>
		<comments>http://www.mind-it.info/2009/10/03/switching-to-wordpress/#comments</comments>
		<pubDate>Sat, 03 Oct 2009 21:32:05 +0000</pubDate>
		<dc:creator>postme</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[Webtechnology]]></category>

		<guid isPermaLink="false">http://www.mind-it.info/?p=124</guid>
		<description><![CDATA[I finally succumbed to ease of use and switched from my bespoke PivotLog installation to WordPress. I thoroughly enjoyed Pivot but when switching from Textdrive to Amazon EC2 I had to change and migrate so many things that I settled for the easier solution; WordPress. It&#8217;s been an ok experience so far, I miss my [...]]]></description>
			<content:encoded><![CDATA[<p>I finally succumbed to ease of use and switched from my bespoke PivotLog installation to WordPress. I thoroughly enjoyed Pivot but when switching from Textdrive to Amazon EC2 I had to change and migrate so many things that I settled for the easier solution; WordPress.</p>
<p><span id="more-124"></span> </p>
<p>It&#8217;s been an ok experience so far, I miss my Atom/XSLT solution mainly because I was quite pleased with my own inventiveness but after the annoying experience with IE8 rendering my client side XSLT solution useless most of the fun went out of that any way.</p>
<p>The WordPress templating is quite horrible, about the worst that PHP is capable of, hopefully that will improve somewhat in the near future although I won&#8217;t get my hope up.</p>
<p>The plugins works fine, it took me a while to figure out not to hack the javascript stuff directly into the templates or posts but rather download the appropriate plugin like the SyntaxHighLighter and use custom tag constructions in the post that don&#8217;t get filtered out by WordPress.</p>
<p>Still need to do some tweaking on the template, it&#8217;s getting there but some improvements to the right column spacing need to be done. I&#8217;ll probably drop the left column so there&#8217;s more space for the blog posts, the code fragments seem a bit too constrained at the moment.</p>
<p>I&#8217;ve gone back to XHTML 1.0 Strict rather than follow the fashionable crowd with HTML 4.01 Strict or HTML 5. I remain convinced that there&#8217;s nothing wrong with XHTML 1.0 Strict and I like the fact that I can process it as XML when I need to.</p>
<img src="http://feeds.feedburner.com/~r/mind-it/Aqwc/~4/DSF0O0477Zw" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.mind-it.info/2009/10/03/switching-to-wordpress/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://www.mind-it.info/2009/10/03/switching-to-wordpress/</feedburner:origLink></item>
		<item>
		<title>Changes to this site</title>
		<link>http://feedproxy.google.com/~r/mind-it/Aqwc/~3/tvQFWLSdwDc/</link>
		<comments>http://www.mind-it.info/2009/10/02/changes-to-this-site/#comments</comments>
		<pubDate>Fri, 02 Oct 2009 19:41:07 +0000</pubDate>
		<dc:creator>Meint Post</dc:creator>
				<category><![CDATA[Atom]]></category>
		<category><![CDATA[Featured]]></category>
		<category><![CDATA[Webtechnology]]></category>
		<category><![CDATA[XML]]></category>
		<category><![CDATA[XSL]]></category>
		<category><![CDATA[CufÃ³n]]></category>
		<category><![CDATA[typeface.js]]></category>
		<category><![CDATA[XHTML]]></category>

		<guid isPermaLink="false">http://www.mind-it.info/?p=18</guid>
		<description><![CDATA[As explained in one of the first posts on this blog this site is basically just one big Atom feed that gets transformed into this blog by using a bit of Apache content negotiation and client side XSLT. Besides some issues with browsers ignoring client side XSLT in a feed and forcing their own rendition [...]]]></description>
			<content:encoded><![CDATA[<p>As explained in one of the first posts on this blog this site is basically just one big Atom feed that gets transformed into this blog by using a bit of Apache content negotiation and client side XSLT. Besides some issues with browsers ignoring client side XSLT in a feed and forcing their own rendition of my feed which was fixed by inserting 512 bytes of crud to throw of the feed sniffing this approach has worked fine for the last four years.</p>
<p><span id="more-18"></span> </p>
<p>Alas these happy years are now over due too Internet Explorer 8. For reasons unknown (and undocumented) IE8 no longer respects the 512 bytes of crud workaround and insists on deploying its &#8220;friendly&#8221; feed view on everything it perceives as being a feed, client side XSLT and 512 bytes workaround be damned.</p>
<p>Given the potential audience for IE8 I can&#8217;t go on with my favoured method and I have decided to switch to a server side XSLT rendering. Given the high level of standardisation available within XSLT I didn&#8217;t have to change a single item in my stylesheet.</p>
<p>Whilst on the experimental track I took some time to play around with <a href="http://typeface.neocracy.org/">typeface.js</a> and <a href="http://wiki.github.com/sorccu/cufon/about">CufÃ³n</a>. I had already used SIFR on this site and I was interested in how it would compare against these newcomers. Both typeface.js and CufÃ³n are completely javascript based solutions that embed their fonts as javascript files in the page. Getting both libraries to work required a bit of tinkering to acquire a feel for their approach but basically all examples and code where up and running in minutes. There&#8217;s not much difference in how both libraries work, they both use javascript with a combination of &lt;canvas&gt; or VML elements. From an aesthetic viewpoint I like CufÃ³n better because the fonts seem crisper than those of typeface.js. This might have something to do with the extensive font rendering process that was created for CufÃ³n. I set the &lt;h1&gt; and &lt;h2&gt; in CufÃ³n and I like the results enough to abandon SIFR. I even tried to set an entire page in CufÃ³n but that to all kinds of amazing behaviour within FireFox (even crashing it) so I decided to let that approach rest. It did however get me started on looking in/back to CSS 3 font-face adoption which seems to be imminent for the large browsers with Safari 3.1 already implementing it. For those of you that use Safari 3.1 (or are using a browser that supports font-face now) I have set the paragraphs in <a href="http://www.josbuivenga.demon.nl/delicious.html">Delicious Roman</a>, a free font from <a href="http://feedme.mind-it.infowww.josbuivenga.demon.nl">Jos Buivenga</a>.</p>
<p>Oh by the way the server side XSLT rendering is done with PHP. All requests for XML files are forwarded by Apache based on a specific <a href="http://httpd.apache.org/docs/trunk/mod/mod_mime.html#addhandler">AddHandler</a> and <a href="http://httpd.apache.org/docs/trunk/mod/mod_actions.html#action">Action</a>.</p>
<pre class="brush: cpp;">
# Handler atom_xslt is associated with xml files
AddHandler atom_xslt xml

# Subsequently handler atom_xslt is associated with index.php
# for actual processing
Action atom_xslt /index.php 

# Force everything to the feed
DirectoryIndex index.xml
</pre>
<p>A simple caching mechanism is applied by the PHP script to render to HTML once and only update the rendered file after either the XML feed or the XSLT stylesheet have been update. Now that I don&#8217;t apply a client side XSLT anymore there&#8217;s no reason to stick with XHTML anymore and I have switched to HTML 4.01 Strict.</p>
<img src="http://feeds.feedburner.com/~r/mind-it/Aqwc/~4/tvQFWLSdwDc" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.mind-it.info/2009/10/02/changes-to-this-site/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://www.mind-it.info/2009/10/02/changes-to-this-site/</feedburner:origLink></item>
	</channel>
</rss><!-- Served from: www.mind-it.info @ 2010-08-10 00:09:40 by W3 Total Cache -->
