Smarty base href Modifier

 Aug, 07 - 2010   no comments   How ToThings that are broken

It appears that Safari 5 will not respect the base href tag when used in a page served via https when the base href indicates a URL with the http protocol. There is probably more to this issue, but I ran across it while working on an Authorize.net integration using their SIM API. After a successful transaction, Authorize.net requests a URL of the developer’s choosing, and proxies the response through their server to the user’s browser. This allows developers to do callback processing of the successful transaction on their server, and display a custom “thank you” page. Brilliant. The problem is, if you have any included CSS, JavaScript, or images in the page, you either need to give them all fully qualified URLs, or use the base tag to specify a root URL to use for all relative link attributes in the page (href, src, action, etc.). I’ve done this same type of integration many times, going back about six years, and have never had a problem using the base href in this scenario. Now, Safari 5 will completely ignore the base href and display a big mess of un-styled markup when you reach the end of the Authorize.net transaction flow.

I do a lot of work with the Smarty template engine, and the site I’m working on now is large, complex, and has a fairly advanced layout with lots of CSS and jQuery goodies. Everything is so abstracted, it’s just not practical to construct a single template for my Authorize.net relay pages, of which there are several. It’s also not practical to change the templates to use fully qualified URLs for everything. So what I did was write a simple Smarty modifier that prepends a specified URL to all of the relative src, href, and action attributes within the supplied string. It also fixes background: url() inline CSS styles. On my relay templates, all I have to do is wrap the contents of the template in a {capture} function, assign the output to a variable, and run it through my modifier. Absolute paths for all. Here’s the modifier code, hopefully it will save someone a few grey hairs.

<?php
/**
 * Smarty plugin
 * @package Smarty
 * @subpackage plugins
 */


/**
 * Smarty base_href modifier plugin
 *
 * Type:     modifier<br>
 * Name:     base_href<br>
 * Purpose:  apply a base URL to all relative
 *				src, href, and background:url() attributes in a string
 * @author   Rob Ruchte <rob care of thirdpartylabs com>
 * @param string
 * @param string
 * @return string
 */
function smarty_modifier_base_href($string, $base_href)
{
	$base_href = (substr($base_href, -1)!='/') ? $base_href.'/':$base_href;

	$patterns = array();
	$patterns[] = '/href=\"[^#]\/?([^\"]*)\"/i';
	$patterns[] = '/src=\"\/?([^\"]*)\"/i';
	$patterns[] = '/action=\"\/?([^\"]*)\"/i';
	$patterns[] = '/background: ?url\(\'?\/?([^\'|\)]*)\'?\)/i';
	$patterns[] = '/background-image: ?url\(\'?\/?([^\'|\)]*)\'?\)/i';
	
	$replacements = array();
	$replacements[] = 'href="'.$base_href.'$1"';
	$replacements[] = 'src="'.$base_href.'$1"';
	$replacements[] = 'action="'.$base_href.'$1"';
	$replacements[] = 'background: url(\''.$base_href.'$1\')';
	$replacements[] = 'background-image: url(\''.$base_href.'$1\')';

    return preg_replace($patterns, $replacements, $string);
}

/* vim: set expandtab: */

?>

Usage:

{capture assign=output}
{include file="include/header.tpl" title="Event Ticket Registration"}
	<div class="span-3" id="leftbar">
		[...]
	</div>
	<div class="span-11 last" id="content">					
		<div style="background: url(/images/feature.jpg);">
			[...]
		</div>					
		<div class="span-11 last" id="copy">
		<div id="breadcrumbs">
			{foreach from=$breadcrumbs item=currNav name=breadcrumbs}
				{if !$smarty.foreach.breadcrumbs.last}<a href="{$currNav.path}">{/if}
				{$currNav.title}
				{if !$smarty.foreach.breadcrumbs.last}</a>&nbsp;&raquo;&nbsp;{/if}
			{/foreach}
		</div>
        <h2>Registration: {$event->getTitle()|escape}</h2>
	    {$purchaseSuccess}
        </div>
    </div>
{include file="include/footer.tpl"}
{/capture}
{$output|base_href:$smarty.const.BASE_URL}

Related articles


Leave a Reply

Your email address will not be published. Fields with * are mandatory.