<?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>Simply Does Not Work &#187; Web Development</title>
	<atom:link href="http://nicholas.piasecki.name/blog/category/programming/web-development/feed/" rel="self" type="application/rss+xml" />
	<link>http://nicholas.piasecki.name/blog</link>
	<description>Confessions of a small business software developer</description>
	<lastBuildDate>Thu, 20 May 2010 23:32:22 +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>Add AVS and CVN to Magento&#8217;s Admin Screen in Just 637 Easy Steps</title>
		<link>http://nicholas.piasecki.name/blog/2009/10/add-avs-and-cvn-to-magentos-admin-screen-in-just-637-easy-steps/</link>
		<comments>http://nicholas.piasecki.name/blog/2009/10/add-avs-and-cvn-to-magentos-admin-screen-in-just-637-easy-steps/#comments</comments>
		<pubDate>Sat, 03 Oct 2009 20:28:51 +0000</pubDate>
		<dc:creator>Nicholas Piasecki</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[Web Development]]></category>
		<category><![CDATA[magento]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[web stuff]]></category>

		<guid isPermaLink="false">http://nicholas.piasecki.name/blog/?p=361</guid>
		<description><![CDATA[We&#8217;ve recently set up a new e-commerce store at Men&#8217;s Underwear Discounters that represents a division of the company that I work for, Skiviez. We decided to save time for this discount store by using Magento, the current darling child in the open source e-commerce platform market segment.

A brief interlude on consulting, documentation, and open [...]]]></description>
			<content:encoded><![CDATA[<div id="attachment_364" class="wp-caption aligncenter" style="width: 310px"><a href="http://nicholas.piasecki.name/blog/wp-content/uploads/2009/10/avs-in-magento.png"><img src="http://nicholas.piasecki.name/blog/wp-content/uploads/2009/10/avs-in-magento-300x113.png" alt="AVS Information In Magento" title="Displaying AVS information in Magento" width="300" height="113" class="size-medium wp-image-364" /></a><p class="wp-caption-text">AVS Information In Magento</p></div>

<p>We&#8217;ve recently set up a new e-commerce store at <a href="http://www.mensunderweardiscounters.com">Men&#8217;s Underwear Discounters</a> that represents a division of the company that I work for, <a href="http://www.skiviez.com">Skiviez</a>. We decided to save time for this discount store by using <a href="http://www.magentocommerce.com">Magento</a>, the current darling child in the open source e-commerce platform market segment.</p>

<h2>A brief interlude on consulting, documentation, and open source</h2>

<p>Now, to be clear, it doesn&#8217;t take much to exceed expectations in the &#8220;open source e-commerce platform&#8221; market because prior to Magento, your options were pretty much limited to <a href="http://www.oscommerce.com">osCommerce</a>, which is quite possibly the most reckless, idiotic excuse of an e-commerce platform that I have seen (and I don&#8217;t like to insult code), and its slightly-less-retarded sibling <a href="http://www.zen-cart.com">Zen Cart</a>. (I will save the osCommerce rants for another post.)</p>

<p>Magento seems to be a dream come true: thousands of man-hours of development into an e-commerce platform for free. So what&#8217;s the catch? While Varien (&#8220;the Magento company&#8221;) has done a great service to the world and the open source community by creating Magento, they&#8217;re still in it to make a buck&#8211;and that&#8217;s not a bad thing&#8211;but you might not realize how they make those bucks until you&#8217;ve started playing around with your own Magento store. They make money on support, consulting, and customization because Magento is <em>huge</em> and poorly documented.</p>

<p>Actually, &#8220;poorly documented&#8221; would imply that there was at least some documentation, and while there truly is some documentation available in the source code and on Varien&#8217;s Magento Web site, in reality, that amount of documentation is a statistical rounding error. And when you actually view your Magento installation in an FTP program, you will be absolutely <em>astounded</em> at the number of directories and files. You can try inspecting the source files to try to put it all together, but a lot of it is &#8220;magic&#8221;: a framework erected at runtime by XML configuration files and PHP&#8217;s idiotic <code>__call</code> mechanism for magic functions that appear at runtime out of thin air. You can see references to a function called <code>getOrder()</code>, for example, grep the entire installation for &#8220;getOrder()&#8221;, and not get any results because the function doesn&#8217;t actually exist at compile time. Personally, I&#8217;ve always considered magic methods to be an extremely unwise idea, a &#8220;too clever&#8221; approach to programming. But for people new to PHP looking to do a little customization to their Magento store, it makes the codebase all the more impenetrable. That&#8217;s more consulting dollars.</p>

<p>You could go to the Magento forums, but you won&#8217;t find too many helpful answers because Magento obviously doesn&#8217;t want to give help for free, since giving help is central to their business model. So if you need help, your best bet is to generally (a) pay for it or (b) hope that you stumble across somebody&#8217;s blog who took the time to post a solution to your exact problem.</p>

<h2>Why do I need to do this, anyway?</h2>

<p>Magento has a lot of stuff built in. But we need to remember that Magento was built by software developers, and software developers generally don&#8217;t understand the problem domain of running an e-commerce business very well. Sure, every software developer has built the pet shop&#8211;products, categories, inventory, orders, how hard could it be?&#8211;but they stop or fail to understand that there&#8217;s a whole class of operations that need to happen after the order has been placed.</p>

<p>One of those operations is fraud analysis. The Address Verification System (AVS) and the Card Verification Number (CVN) system for credit cards enable merchants to help determine if a credit card has been fraudulently used on an order. AVS will tell the merchant whether or not the billing address specified by the customer matches or partially matches the billing address on the credit card&#8217;s billing statement. And the CVN number represents the number that (supposedly) exists in only two places in the world: on the physical credit card and in the issuing bank&#8217;s files. If a CVN doesn&#8217;t match and the AVS doesn&#8217;t match, then there&#8217;s a good bet that there is something wrong with the order.</p>

<p>Because software developers are nerds, this information doesn&#8217;t currently display by default in Magento&#8217;s administration section. So let&#8217;s add it.</p>

<h2>Can&#8217;t I just edit the template?</h2>

<p>I&#8217;m talking about adding this AVS display functionality in the context of the CyberSource extension for Magento. After spelunking through the myriad files and directories, I discovered that the Varien-provided CyberSource extension is saving the AVS (<code>setCcAvsStatus()</code>) and CVN (<code>setCcCidStatus()</code>) information when it authorizes the card, but it doesn&#8217;t display in the information block in the administration section.</p>

<p>While you could just modify <code>app/design/adminhtml/default/default/template/cybersource/info.phtml</code> directly (yes, that is the actual path to the file that displays the little &#8220;Payment&#8221; block), your changes would be lost and overwritten in the future if you ever upgraded the CyberSource extension via Magento Connect. That&#8217;s obviously less than ideal.</p>

<p>A better way would be to use Magento&#8217;s &#8220;rewrite&#8221; mechanism. We&#8217;ll create our own Magento module and instruct Magento to replace the CyberSource extension&#8217;s information block with our own.</p>

<h2>Creating our own module</h2>

<p>First, we&#8217;ll create a new empty directory to hold our files. Let&#8217;s call it <code>avsdisplay</code>. Then we&#8217;ll create <code>code</code>, <code>etc</code>, and <code>design</code> subdirectories. These directories mirror the subdirectories in the <code>app</code> folder of your Magento installation.</p>

<p>In the <code>etc</code> directory, we need to create an XML configuration file. Magento scans this directory at runtime for XML files and reads them to know which modules to load. I&#8217;ve named my configuration file <code>Mud_Avsdisplay.xml</code>, and the naming is very important. (Magento uses a mixture of convention and configuration.) The part of the filename before the underscore is your &#8220;namespace,&#8221; since PHP doesn&#8217;t support namespaces. And the part of the filename after the underscore is the name of your module. Mine is &#8220;Avsdisplay.&#8221; Don&#8217;t try to use something like &#8220;AvsDisplay,&#8221; however, because that would break Magento&#8217;s convention as we&#8217;ll see in a moment.</p>

<p>Inside this file, we tell Magento to load our module in the <code>local</code> pool and to actually run it (by setting &#8220;active&#8221; to &#8220;true&#8221;). (The other pools are <code>core</code>, for those modules provided by Varien, and <code>community</code>, for those modules that you can download via Magento Connect.)</p>


<div class="wp_syntax"><div class="code"><pre class="xml" style="font-family:monospace;"><span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;?xml</span> <span style="color: #000066;">version</span>=<span style="color: #ff0000;">&quot;1.0&quot;</span><span style="color: #000000; font-weight: bold;">?&gt;</span></span>
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;config<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
	<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;modules<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
		<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;Mud_Avsdisplay<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
			<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;active<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>true<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/active<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
			<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;codePool<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>local<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/codePool<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
		<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/Mud_Avsdisplay<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
	<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/modules<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/config<span style="color: #000000; font-weight: bold;">&gt;</span></span></span></pre></div></div>


<p>Now it&#8217;s time to create the meat of the module. In the code folder, create a <code>local</code> directory. Within that, create a directory named after your chosen namespace (<code>Mud</code> in my example) and within that yet another subdirectory named after your module (<code>Avsdisplay</code> in my example). (This is why naming was important. If I had called it &#8220;Mud_AvsDisplay,&#8221; with a capital &#8216;D&#8217;, then Magento would have looked in <code>app/code/local/Mud/Avs/Display</code> for my module instead of <code>app/code/local/Mud/Avsdisplay</code>.)</p>

<p>Within your module directory, you&#8217;ll need to create three <em>more</em> subdirectories: <code>Block</code>, <code>etc</code>, and <code>Helper</code>. When it&#8217;s all said and done, you&#8217;ll end up with a hierarchy that looks like this (ignore the &#8220;design&#8221; directory, we&#8217;ll get to that later):</p>

<div id="attachment_367" class="wp-caption aligncenter" style="width: 202px"><a href="http://nicholas.piasecki.name/blog/wp-content/uploads/2009/10/directories.png"><img src="http://nicholas.piasecki.name/blog/wp-content/uploads/2009/10/directories.png" alt="Directory Structure" title="directories" width="192" height="236" class="size-full wp-image-367" /></a><p class="wp-caption-text">Directory Structure</p></div>

<h3>Creating the block</h3>

<p>Next, we need to create the &#8220;block&#8221; that we&#8217;ll be replacing. After searching through the codebase, I figured out that I wanted to replace the <code>Mage_Cybersource_Block_Info</code> block (for reference, by Magento&#8217;s convention, that file lives in <code>app/core/Mage/Cybersource/Block/Info.php</code> &#8212; see the convention?). But I really only want to add stuff to it, not replace it outright, so I&#8217;ll create a new file in my <code>Block</code> folder called <code>Info.php</code> that extends that class. Something like:</p>


<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">&lt;?php</span>
&nbsp;
<span style="color: #000000; font-weight: bold;">class</span> Mud_AvsDisplay_Block_Info <span style="color: #000000; font-weight: bold;">extends</span> Mage_Cybersource_Block_Info
<span style="color: #009900;">&#123;</span>
	<span style="color: #666666; font-style: italic;">// Yes, these really have to be protected, not private, due to more Magento</span>
	<span style="color: #666666; font-style: italic;">// &quot;magic&quot;</span>
	protected <span style="color: #000088;">$avsDescriptions</span> <span style="color: #339933;">=</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span>
		<span style="color: #666666; font-style: italic;">// Snipped for brevity; download file at end of blog post</span>
	<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
	protected <span style="color: #000088;">$ccCidDescriptions</span> <span style="color: #339933;">=</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span>
		<span style="color: #666666; font-style: italic;">// Snipped for brevity; download file at end of blog post</span>
	<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
	protected <span style="color: #000000; font-weight: bold;">function</span> _construct<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>
	<span style="color: #009900;">&#123;</span>
		parent<span style="color: #339933;">::</span>_construct<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;">-&gt;</span><span style="color: #004000;">setTemplate</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'avsdisplay/info.phtml'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	<span style="color: #009900;">&#125;</span>
&nbsp;
	<span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> getAvsStatusDescription<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>
	<span style="color: #009900;">&#123;</span>
		<span style="color: #000088;">$info</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getInfo</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
		<span style="color: #000088;">$avsCode</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$info</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getCcAvsStatus</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
		<span style="color: #000088;">$avsDescription</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">'Unrecognized response code.'</span><span style="color: #339933;">;</span>
&nbsp;
		<span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #990000;">array_key_exists</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$avsCode</span><span style="color: #339933;">,</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">avsDescriptions</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span>
		<span style="color: #009900;">&#123;</span>
			<span style="color: #000088;">$avsDescription</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">avsDescriptions</span><span style="color: #009900;">&#91;</span><span style="color: #000088;">$avsCode</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
		<span style="color: #009900;">&#125;</span>
&nbsp;
		<span style="color: #b1b100;">return</span> <span style="color: #000088;">$avsDescription</span><span style="color: #339933;">;</span>
	<span style="color: #009900;">&#125;</span>
&nbsp;
	<span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> getCcCidDescription<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>
	<span style="color: #009900;">&#123;</span>
		<span style="color: #000088;">$info</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getInfo</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
		<span style="color: #000088;">$ccCidCode</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$info</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getCcCidStatus</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
		<span style="color: #000088;">$ccCidDescription</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">'Unrecognized response code.'</span><span style="color: #339933;">;</span>
&nbsp;
		<span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #990000;">array_key_exists</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$ccCidCode</span><span style="color: #339933;">,</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">ccCidDescriptions</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span>
		<span style="color: #009900;">&#123;</span>
			<span style="color: #000088;">$ccCidDescription</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">ccCidDescriptions</span><span style="color: #009900;">&#91;</span><span style="color: #000088;">$ccCidCode</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
		<span style="color: #009900;">&#125;</span>
&nbsp;
		<span style="color: #b1b100;">return</span> <span style="color: #000088;">$ccCidDescription</span><span style="color: #339933;">;</span>
	<span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>


<p>Okay, this makes sense. I&#8217;m doing everything the old CyberSource info block did, except I added two new functions that give me human-friendly descriptions of the AVS and CVN codes, and I&#8217;m setting the template to something called <code>avsdisplay/info.phtml</code> instead of <code>cybersouce/info.phtml</code>. How this comes into play will make sense in a minute.</p>

<h3>Creating the helper</h3>

<p>In my <code>Helper</code> directory, I need to add a <code>Data.php</code> file that looks like this:</p>


<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">&lt;?php</span>
&nbsp;
<span style="color: #000000; font-weight: bold;">class</span> Mud_Avsdisplay_Helper_Data <span style="color: #000000; font-weight: bold;">extends</span> Mage_Core_Helper_Abstract
<span style="color: #009900;">&#123;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>


<p>That&#8217;s right, it does nothing except inherit from a Magento-provided abstract class. What is a helper? I have no idea, but you have to do it&#8211;Magento looks for this file.</p>

<h3>Telling Magento to do the swap</h3>

<p>In my <code>etc</code> directory, I need to add a <code>config.xml</code> file that will tell Magento some information about my module and, most importantly, that I want to be swapped with the CyberSource extension&#8217;s info block:</p>


<div class="wp_syntax"><div class="code"><pre class="xml" style="font-family:monospace;"><span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;?xml</span> <span style="color: #000066;">version</span>=<span style="color: #ff0000;">&quot;1.0&quot;</span><span style="color: #000000; font-weight: bold;">?&gt;</span></span>
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;config<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
	<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;modules<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
		<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;Mud_Avsdisplay<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
			<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;version<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>0.0.1<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/version<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
		<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/Mud_Avsdisplay<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
	<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/modules<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
	<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;global<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
		<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;helpers<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
			<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;avsdisplay<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
				<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;class<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>Mud_Avsdisplay_Helper_Data<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/class<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
			<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/avsdisplay<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
		<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/helpers<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
		<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;blocks<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
			<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;cybersource<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
				<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;rewrite<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
					<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;info<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>Mud_Avsdisplay_Block_Info<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/info<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
				<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/rewrite<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
			<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/cybersource<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
		<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/blocks<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
	<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/global<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/config<span style="color: #000000; font-weight: bold;">&gt;</span></span></span></pre></div></div>


<p>Under <code>&lt;modules&gt;</code>, I&#8217;m just telling Magento the version number of my module. Under <code>&lt;global&gt;</code>, I say that I want to &#8220;rewrite&#8221; the CyberSource info block with my own class named <code>Mud_Avsdisplay_Block_Info</code>, which, by convention, Magento will look for in <code>[module-root]/Mud/Avsdisplay/Block/Info.php</code>. That is the file that I just created. Great.</p>

<h3>Finally, writing the template that displays the information</h3>

<p>But we haven&#8217;t actually changed any HTML at this point! Remember in my <code>Info.php</code> file where I set the template to something called <code>info.phtml</code>? Well, I need to create that file. At the top of my module folder&#8211;the one with the <code>code</code> and <code>etc</code> subdirectories&#8211;I&#8217;ll need to create some more subdirectories. A lot of them. In fact, I&#8217;ll need to create a bunch of empty directories that look like this:</p>

<p><a href="http://nicholas.piasecki.name/blog/wp-content/uploads/2009/10/design-directories.png"><img src="http://nicholas.piasecki.name/blog/wp-content/uploads/2009/10/design-directories.png" alt="Design Directory Structure" title="Design Directory Structure" width="164" height="133" class="aligncenter size-full wp-image-368" /></a></p>

<p>In the bottom-most subdirectory, I&#8217;ll create the <code>info.phtml</code> file. This is a PHP file, except that when I use the <code>$this</code> pseudo-variable in this file, <code>$this</code> will be pointing to an instance of my <code>Mud_Avsdisplay_Block_Info</code> class. So I&#8217;ll be able to call my <code>getAvsStatusDescription()</code> method here among other things:</p>


<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">&lt;?php</span>
	<span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$info</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getInfo</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span>
	<span style="color: #009900;">&#123;</span>
		<span style="color: #000000; font-weight: bold;">?&gt;</span>
			&lt;strong&gt;<span style="color: #000000; font-weight: bold;">&lt;?php</span> <span style="color: #b1b100;">echo</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getMethod</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getTitle</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #000000; font-weight: bold;">?&gt;</span>&lt;/strong&gt;&lt;br /&gt;
			&lt;strong&gt;Type:&lt;/strong&gt; <span style="color: #000000; font-weight: bold;">&lt;?php</span> <span style="color: #b1b100;">echo</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>__<span style="color: #009900;">&#40;</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getCcTypeName</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #000000; font-weight: bold;">?&gt;</span>&lt;br /&gt;
			&lt;strong&gt;Number:&lt;/strong&gt; xxxx-<span style="color: #000000; font-weight: bold;">&lt;?php</span> <span style="color: #b1b100;">echo</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>__<span style="color: #009900;">&#40;</span><span style="color: #000088;">$info</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getCcLast4</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #000000; font-weight: bold;">?&gt;</span>&lt;br /&gt;
			&lt;strong&gt;Expiry:&lt;/strong&gt; <span style="color: #000000; font-weight: bold;">&lt;?php</span> <span style="color: #b1b100;">echo</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>__<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'%s/%s'</span><span style="color: #339933;">,</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getCcExpMonth</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span> <span style="color: #000088;">$info</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getCcExpYear</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #000000; font-weight: bold;">?&gt;</span>&lt;br /&gt;
			&lt;strong&gt;AVS:&lt;/strong&gt; (<span style="color: #000000; font-weight: bold;">&lt;?php</span> <span style="color: #b1b100;">echo</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>__<span style="color: #009900;">&#40;</span><span style="color: #000088;">$info</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getCcAvsStatus</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #000000; font-weight: bold;">?&gt;</span>) <span style="color: #000000; font-weight: bold;">&lt;?php</span> <span style="color: #b1b100;">echo</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>__<span style="color: #009900;">&#40;</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getAvsStatusDescription</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #000000; font-weight: bold;">?&gt;</span>&lt;br /&gt;
			&lt;strong&gt;CCID:&lt;/strong&gt; (<span style="color: #000000; font-weight: bold;">&lt;?php</span> <span style="color: #b1b100;">echo</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>__<span style="color: #009900;">&#40;</span><span style="color: #000088;">$info</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getCcCidStatus</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #000000; font-weight: bold;">?&gt;</span>) <span style="color: #000000; font-weight: bold;">&lt;?php</span> <span style="color: #b1b100;">echo</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>__<span style="color: #009900;">&#40;</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getCcCidDescription</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #000000; font-weight: bold;">?&gt;</span>&lt;br /&gt;
		<span style="color: #000000; font-weight: bold;">&lt;?php</span>
	<span style="color: #009900;">&#125;</span>
<span style="color: #000000; font-weight: bold;">?&gt;</span></pre></div></div>


<h2>Conclusions and delusions</h2>

<p>And that&#8217;s it. Upload this entire directory structure to your Magento installation&#8217;s <code>app</code> directory, <em>merging</em> the contents as necessary, and you should be able to see AVS information for your CyberSource orders in the administration section.</p>

<p>How did I figure out how to learn all of this? It was mostly by lots of Googling, picking apart existing modules to see how they were organized, and piecing together lots of blog posts. I hope this helps someone out there. Good luck!</p>

<p><a href='http://nicholas.piasecki.name/blog/wp-content/uploads/2009/10/avsdisplay-0.0.2.zip'>Download the code used in this article.</a></p>
]]></content:encoded>
			<wfw:commentRss>http://nicholas.piasecki.name/blog/2009/10/add-avs-and-cvn-to-magentos-admin-screen-in-just-637-easy-steps/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>When in doubt: OpenID is a bad idea for your Web site</title>
		<link>http://nicholas.piasecki.name/blog/2009/07/when-in-doubt-openid-is-a-bad-idea-for-your-web-site/</link>
		<comments>http://nicholas.piasecki.name/blog/2009/07/when-in-doubt-openid-is-a-bad-idea-for-your-web-site/#comments</comments>
		<pubDate>Tue, 07 Jul 2009 00:15:36 +0000</pubDate>
		<dc:creator>Nicholas Piasecki</dc:creator>
				<category><![CDATA[Rants]]></category>
		<category><![CDATA[Web Development]]></category>
		<category><![CDATA[design]]></category>
		<category><![CDATA[openid]]></category>
		<category><![CDATA[web stuff]]></category>

		<guid isPermaLink="false">http://nicholas.piasecki.name/blog/?p=291</guid>
		<description><![CDATA[Well, that&#8217;s a bit of an inflammatory title. But this screenshot speaks volumes:

What has happened here is that my OpenID provider, Verisign Labs, is down for some reason while StackOverflow, the site that I&#8217;m trying to log on to, is still up.

A single point of failure

While this isn&#8217;t a big deal for a site that [...]]]></description>
			<content:encoded><![CDATA[<p>Well, that&#8217;s a bit of an inflammatory title. But this screenshot speaks volumes:</p>

<div id="attachment_292" class="wp-caption aligncenter" style="width: 310px"><a href="http://nicholas.piasecki.name/blog/wp-content/uploads/2009/07/openid.png"><img src="http://nicholas.piasecki.name/blog/wp-content/uploads/2009/07/openid-300x136.png" alt="I can&#039;t log in!" title="openid" width="300" height="136" class="size-medium wp-image-292" /></a><p class="wp-caption-text">I can't log in!</p></div>

<p>What has happened here is that my <a href="http://openid.net/">OpenID</a> provider, <a href="https://pip.verisignlabs.com/">Verisign Labs</a>, is down for some reason while StackOverflow, the site that I&#8217;m trying to log on to, is still up.</p>

<h2>A single point of failure</h2>

<p>While this isn&#8217;t a big deal for a site that I use recreationally, it is kind of a big deal in principle: all sites that use OpenID are inaccessible to me, since I only have this single OpenID provider. It is a single point of failure.</p>

<p>Sure, I could have multiple OpenID accounts, such as a &#8220;backup&#8221; OpenID account at another provider, but this defeats the purpose of OpenID, of having a central point of authority regarding my online identity. If I have to create a second OpenID provider, I might as well just make a native username and password at the site that I&#8217;m trying to log into. I could also be my own OpenID provider, but I shouldn&#8217;t have to do that, and the average OpenID consumer is not going to know how to do that, anyway. It&#8217;s faster just to create a &#8220;native account&#8221; at the Web site that I&#8217;m trying to access and be done with it.</p>

<h2>An unnecessary third-party dependency</h2>

<p>For any e-commerce business, it&#8217;s usually unwise to take on <em>any</em> third-party dependency. Speaking from experience, that third-party will go down for some reason at some point and <em>you</em> will be the one fielding angry customer support calls for something that isn&#8217;t your problem. Even worse, if something as critical as authentication through OpenID goes down, then you&#8217;re losing sales, and that means that you&#8217;re not doing your job.</p>

<p>If you&#8217;re going to add OpenID to an e-commerce Web site or a &#8220;mission-critical&#8221; Web site, then you should implement it as a red-headed step-child, &#8220;convenience only&#8221; implementation; this way, your users can fall back onto their &#8220;native credentials&#8221; (those stored in <em>your</em> database) when their preferred OpenID provider explodes. In this way, OpenID is a shortcut, not a single authoritative source, much how like customers use PayPal&#8217;s Express Checkout to save time when entering payment and addressing information during checkout. If PayPal&#8217;s Web Service API goes down (and believe you me, it&#8217;s gone down several times this year alone), customers can still begrudgingly use the &#8220;native checkout&#8221; to complete their purchase. Some lost conversions due to the inconvenience&#8211;and for incorrectly faulting the integrity of your Web site for the third party&#8217;s failure&#8211;but at least <em>the sale is still actually possible.</em> If OpenID is your only authentication mechanism, and a user&#8217;s OpenID provider goes down, then that user is simply screwed. The onus should not be on the consumer to provide a backup authentication mechanism to <em>your</em> Web site.</p>

<h2>It&#8217;s just complicated</h2>

<p>OpenID is still just too complicated. I&#8217;m not the smartest software developer in the world by any means, but if I can barely wrap my mind around it enough just to get my first account, then I am 100% certain that our customers would have problems with it:</p>

<ul>
<li>Why do I have to go to some third-party provider to sign in? That doesn&#8217;t make any sense.</li>
<li>Why should I trust that third-party provider? I&#8217;m not even sure that I trust you!</li>
<li>I still don&#8217;t know which third-party provider to use! Oh well, I guess I&#8217;ll use Verisign, at least I&#8217;ve heard of them.</li>
<li>What happens to my credentials when that third-party provider goes under?</li>
<li>Can I call your business to reset my password when I forget it? I will anyway!</li>
</ul>

<p>Even with our &#8220;native registration&#8221; of e-mail addresses and passwords, we had to use an Amazon.com style login form because users kept filling out the &#8220;new customer&#8221; form even when they already had an account:</p>

<blockquote>
  <p>Login screen. Amazon&#8217;s sign-in screen remains a model to be emulated, minimizing the common problem of new customers who try to log in without having registered. Amazon presents two questions in linear order: (1) &#8220;What is your email address?&#8221; and (2) &#8220;Do you have an Amazon.com password?&#8221; For the second question, users can select one of two radio buttons: &#8220;No, I am a new customer,&#8221; or &#8220;Yes, I have a password.&#8221; Many other sites present the new- and established-user sections side-by-side, and thereby divert new users to the established-user section through the magnetic attraction of type-in fields. &#8212; Jakob Niesen, <a href="http://www.useit.com/alertbox/20050725.html">useit.com</a></p>
</blockquote>

<p>When our users have trouble navigating two fields and a radio button, you can imagine the hilarity that ensues when they are presented with multiple authentication mechanisms. Especially one that doesn&#8217;t ask for a password.</p>

<h2>A leaky abstraction</h2>

<p>While the idea of consolidating your online identity to a single source sounds like a good idea, it simply does not work in practice. Not even the United States government has a consistent picture of my identity: my identity is stored with the IRS, the Social Security Administration, the United States Postal service, the Virginia Department of Taxation, the Virginia Department of Motor Vehicles, and the City of Richmond&#8217;s Voter Registrar. These are all <em>independent</em> identity stores that, in general, agree that I am who I say that I am, but each identity is stored and updated independently of one another. Consider OpenID the RealID act of the Internet: what happens when your centralized identity gets screwed up? It&#8217;s an existentialist crisis and you just have to deal with it: identity is what other people say you are; it&#8217;s <em>not</em> what <em>you</em> say you are. Better to have multiple voices confirming your identity than just one.</p>

<h2>Conclusions and Delusions</h2>

<p>If you&#8217;re implementing a social-oriented Web site that is designed to integrate with Facebook or some of the Web-2.0-savvy consumers, then OpenID might make sense. Those nerds may have heard of OpenID and know how to use it, foibles and all. Until the dust settles on OpenID, though, I wouldn&#8217;t add it to a commercial site even if you paid for it: nobody has asked for it; it will cause problems.</p>

<p>My general recommendation would be to have the usual in house username and password mechanism that can be supplemented by OpenID. But realize that each alternative identification mechanism that you add runs the risk of customer confusion, bugs, security holes, and increased customer support. When in doubt, leave it out.</p>
]]></content:encoded>
			<wfw:commentRss>http://nicholas.piasecki.name/blog/2009/07/when-in-doubt-openid-is-a-bad-idea-for-your-web-site/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>On IIS 6, Content-Location, Internal IP Addresses, and URL Redirection</title>
		<link>http://nicholas.piasecki.name/blog/2008/12/on-iis-6-content-location-internal-ip-addresses-and-url-redirection/</link>
		<comments>http://nicholas.piasecki.name/blog/2008/12/on-iis-6-content-location-internal-ip-addresses-and-url-redirection/#comments</comments>
		<pubDate>Fri, 05 Dec 2008 14:36:51 +0000</pubDate>
		<dc:creator>Nicholas Piasecki</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[Web Development]]></category>
		<category><![CDATA[asp.net]]></category>
		<category><![CDATA[csharp]]></category>
		<category><![CDATA[iis]]></category>
		<category><![CDATA[web stuff]]></category>

		<guid isPermaLink="false">http://nicholas.piasecki.name/blog/?p=103</guid>
		<description><![CDATA[One of our automated security scans of our Web site turned up a low priority notice that our server was revealing its internal IP address on some redirect requests. It&#8217;s a &#8220;feature&#8221; of IIS that occurs when a client requests a resource via HTTP 1.0 (or without the Host header) that results in a redirection. [...]]]></description>
			<content:encoded><![CDATA[<p>One of our automated security scans of our Web site turned up a low priority notice that our server was revealing its internal IP address on some redirect requests. It&#8217;s a &#8220;feature&#8221; of IIS that occurs when a client requests a resource via HTTP 1.0 (or without the Host header) that results in a redirection. The output of a telnet session to such a resource looks something like this:</p>


<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #7a0874; font-weight: bold;">&#91;</span>npiaseck ~<span style="color: #7a0874; font-weight: bold;">&#93;</span>$ telnet www.example.com <span style="color: #000000;">80</span>
Trying 10.1.10.38...
Connected to www.example.com <span style="color: #7a0874; font-weight: bold;">&#40;</span>10.1.10.38<span style="color: #7a0874; font-weight: bold;">&#41;</span>.
Escape character is <span style="color: #ff0000;">'^]'</span>.
GET <span style="color: #000000; font-weight: bold;">/</span>Media HTTP<span style="color: #000000; font-weight: bold;">/</span><span style="color: #000000;">1.0</span>
&nbsp;
HTTP<span style="color: #000000; font-weight: bold;">/</span><span style="color: #000000;">1.1</span> <span style="color: #000000;">301</span> Moved Permanently
Content-Length: <span style="color: #000000;">152</span>
Content-Type: text<span style="color: #000000; font-weight: bold;">/</span>html
Location: http:<span style="color: #000000; font-weight: bold;">//</span>10.1.10.38<span style="color: #000000; font-weight: bold;">/</span>Media<span style="color: #000000; font-weight: bold;">/</span>
Server: Microsoft-IIS<span style="color: #000000; font-weight: bold;">/</span><span style="color: #000000;">6.0</span>
Date: Fri, 05 Dec <span style="color: #000000;">2008</span> <span style="color: #000000;">13</span>:<span style="color: #000000;">50</span>:00 GMT
Connection: close
&nbsp;
<span style="color: #000000; font-weight: bold;">&lt;</span><span style="color: #c20cb9; font-weight: bold;">head</span><span style="color: #000000; font-weight: bold;">&gt;&lt;</span>title<span style="color: #000000; font-weight: bold;">&gt;</span>Document Moved<span style="color: #000000; font-weight: bold;">&lt;/</span>title<span style="color: #000000; font-weight: bold;">&gt;&lt;/</span><span style="color: #c20cb9; font-weight: bold;">head</span><span style="color: #000000; font-weight: bold;">&gt;</span>
<span style="color: #000000; font-weight: bold;">&lt;</span>body<span style="color: #000000; font-weight: bold;">&gt;&lt;</span>h1<span style="color: #000000; font-weight: bold;">&gt;</span>Object Moved<span style="color: #000000; font-weight: bold;">&lt;/</span>h1<span style="color: #000000; font-weight: bold;">&gt;</span>
This document may be found <span style="color: #000000; font-weight: bold;">&lt;</span>a <span style="color: #007800;">HREF</span>=<span style="color: #ff0000;">&quot;http://10.1.10.38/Media/&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span>here<span style="color: #000000; font-weight: bold;">&lt;/</span>a<span style="color: #000000; font-weight: bold;">&gt;</span>
<span style="color: #000000; font-weight: bold;">&lt;/</span>body<span style="color: #000000; font-weight: bold;">&gt;</span>
&nbsp;
Connection closed by foreign host.</pre></div></div>


<p>I&#8217;ve made up an internal IP address, but the point is that IIS is inserting the internal IP address in the body of the document as well as the Location header. If you make the same request with the Host header supplied, such as in <code>Host: www.example.com</code>, then IIS would use <code>www.example.com</code> instead of supplying the IP address.</p>

<p>The recommended Microsoft solution is detailed in <a href="http://support.microsoft.com/kb/834141">KB834141</a>. Namely, you edit the <code>SetHostName</code> metabase entry for the Web site to <code>www.example.com</code>, and now IIS will use that instead of the IP address in the above redirection scenario. Easy as pie, right?</p>

<p>Well, that change broke some code. For reasons that are not clear to me, here&#8217;s the mechanism by which IIS 6 determines what to use in these redirect requests:</p>

<ol>
<li>Is the <code>UseHostName</code> property set to <code>true</code>? If so, use the machine&#8217;s host name.</li>
<li>Is the <code>SetHostName</code> property set to some value? If so, use that value.</li>
<li>Is a <code>Host</code> header supplied in the HTTP request? If so, use that value.</li>
<li>If all of the above fail, just use the IP address, which is probably internal.</li>
</ol>

<p>For search engine optimization reasons, all of the requests on our Web site redirect all requests that come in without the <code>www</code> subdomain to ones with the <code>www</code> subdomain. This prevents Google from dinging us for having duplicated content. The code was implemented as an ASP.NET HTTP module that ran before every request and inspected the incoming URL by looking at the <code>HttpContext.Current.Request.Url.OriginalString</code> property. If the domain didn&#8217;t match, then it issued a permanent redirect.</p>

<p>The problem with the above precedence order is that IIS will substitute the value of <code>HTTP_HOST</code> and other server variables passed into ASP.NET with the <code>SetHostName</code> value, not the <code>Host</code> header if so supplied. The net effect is that our redirection method suddenly stopped working because the code was always seeing the <code>SetHostName</code> value, <code>www.example.com</code>, regardless of the URL that was actually used to make the request. To make matters worse, if we were to set the <code>UseHostName</code> property, the code would <em>always</em> see a mismatch and enter a redirect loop. Neither are desirable scenarios.</p>

<p>The solution is to change the code to inspect the <code>Host</code> header directly, if present, instead of looking at the URL as passed into the server variables array. It ends up looking something like this:</p>


<div class="wp_syntax"><div class="code"><pre class="csharp" style="font-family:monospace;"><span style="color: #0600FF;">private</span> <span style="color: #0600FF;">void</span> OnContextBeginRequest<span style="color: #000000;">&#40;</span><span style="color: #FF0000;">object</span> sender, EventArgs e<span style="color: #000000;">&#41;</span>
<span style="color: #000000;">&#123;</span>
	HttpContext context<span style="color: #008000;">;</span>
	<span style="color: #FF0000;">string</span> originalRequestHost<span style="color: #008000;">;</span>
	<span style="color: #FF0000;">int</span> portIndex<span style="color: #008000;">;</span>
	HttpRequest request<span style="color: #008000;">;</span>
	<span style="color: #FF0000;">string</span> redirectUri<span style="color: #008000;">;</span>
&nbsp;
	context <span style="color: #008000;">=</span> HttpContext.<span style="color: #0000FF;">Current</span><span style="color: #008000;">;</span>
	request <span style="color: #008000;">=</span> context.<span style="color: #0000FF;">Request</span><span style="color: #008000;">;</span>
&nbsp;
	originalRequestHost <span style="color: #008000;">=</span> request.<span style="color: #0000FF;">Headers</span><span style="color: #000000;">&#91;</span><span style="color: #666666;">&quot;Host&quot;</span><span style="color: #000000;">&#93;</span><span style="color: #008000;">;</span>
&nbsp;
	<span style="color: #008080; font-style: italic;">// Some clients will pass in the port number in the Host header if</span>
	<span style="color: #008080; font-style: italic;">// it's not going over port 80</span>
	portIndex <span style="color: #008000;">=</span> originalRequestHost.<span style="color: #0000FF;">LastIndexOf</span><span style="color: #000000;">&#40;</span><span style="color: #666666;">':'</span><span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
	<span style="color: #0600FF;">if</span> <span style="color: #000000;">&#40;</span>portIndex <span style="color: #008000;">!=</span> <span style="color: #008000;">-</span><span style="color: #FF0000;">1</span><span style="color: #000000;">&#41;</span>
	<span style="color: #000000;">&#123;</span>
		originalRequestHost <span style="color: #008000;">=</span> 
			originalRequestHost.<span style="color: #0000FF;">Substring</span><span style="color: #000000;">&#40;</span><span style="color: #FF0000;">0</span>, portIndex<span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
	<span style="color: #000000;">&#125;</span>
&nbsp;
	<span style="color: #0600FF;">if</span> <span style="color: #000000;">&#40;</span>originalRequestHost <span style="color: #008000;">!=</span> <span style="color: #0600FF;">null</span> <span style="color: #008000;">&amp;&amp;</span> originalRequestHost <span style="color: #008000;">!=</span> mPreferredSubdomain<span style="color: #000000;">&#41;</span>
	<span style="color: #000000;">&#123;</span>
		redirectUri <span style="color: #008000;">=</span> <span style="color: #FF0000;">string</span>.<span style="color: #0000FF;">Format</span><span style="color: #000000;">&#40;</span>
			<span style="color: #666666;">&quot;http://{0}{1}{2}&quot;</span>,
			mPreferredSubdomain, 
			request.<span style="color: #0000FF;">Url</span>.<span style="color: #0000FF;">Port</span> <span style="color: #008000;">!=</span> <span style="color: #FF0000;">80</span> <span style="color: #008000;">?</span> <span style="color: #666666;">&quot;:&quot;</span> <span style="color: #008000;">+</span> request.<span style="color: #0000FF;">Url</span>.<span style="color: #0000FF;">Port</span>.<span style="color: #0000FF;">ToString</span><span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span> <span style="color: #008000;">:</span> <span style="color: #FF0000;">string</span>.<span style="color: #0000FF;">Empty</span>,
			request.<span style="color: #0000FF;">RawUrl</span><span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
		cLog.<span style="color: #0000FF;">InfoFormat</span><span style="color: #000000;">&#40;</span><span style="color: #666666;">&quot;Redirecting from to {0} (domain: {1}, preferred: {2}).&quot;</span>,
			redirectUri, originalRequestHost, mPreferredSubdomain<span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
		context.<span style="color: #0000FF;">Response</span>.<span style="color: #0000FF;">Redirect</span><span style="color: #000000;">&#40;</span>redirectUri, <span style="color: #0600FF;">true</span><span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
	<span style="color: #000000;">&#125;</span>
<span style="color: #000000;">&#125;</span></pre></div></div>


<p>The code looks at the host header. If it&#8217;s set, and doesn&#8217;t match, then it redirects. (It does a little bit of finagling to strip off the port number if a non-standard port is used in the request.)</p>

<p>With this code in place, we can now use the <code>SetHostName</code> property and still have our URL redirection work properly for HTTP/1.1 requests. We&#8217;re out of luck when it comes to HTTP/1.0 requests, but this is something that we can live with.</p>
]]></content:encoded>
			<wfw:commentRss>http://nicholas.piasecki.name/blog/2008/12/on-iis-6-content-location-internal-ip-addresses-and-url-redirection/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
	</channel>
</rss>
