Nov 28

I do a lot of web design, and I use the Smarty templating engine for all of my PHP websites.  It is a fantastic template system, designed for rapid development, and it succeeds at everything it does.

Well, almost everything.

Smarty has modifiers, which allow you to control data dynamically in your templates.  A lot of people complain that this feature of Smarty puts too much logic in the template system, which by its very nature is supposed to seperate business logic from display logic.  However, some modifiers such as “capitalize” fit under display logic as far as I am concerned.  One limitation of this modifier is that it does not handle contractions very well at all.

Take this for example:

example.tpl:

<br /> {assign value=&#8221;max&#8217;s horse didn&#8217;t fall. &#8217;someone&#8217; is coming.  they&#8217;re here!&#8221; var=&#8221;capt&#8221;}<br /> {$capt|capitalize}<br />
Output:
Max’S Horse Didn’T Fall. ‘Someone’ Is Coming. They’Re Here!

As you can see, Smarty treats the apostrophe as a word boundary, resulting in incorrect capitalization.  The way to fix this behavior is to modify [smarty]/libs/plugins/modifier.capitalize.php.


function smarty_modifier_capitalize($string, $uc_digits = false)
{
//replace common contraction endings with placeholders
//that PCRE will not see as a word boundary
$apos = array(&#8217;n't &#8216;,&#8217;&#8217;s &#8216;,&#8221;re &#8216;);
$tmps = array(&#8217;n__apos__t &#8216;,&#8217;__apos__s &#8216;,&#8217;__apos__re &#8216;);
$string = str_replace($apos,$tmps,$string);
//do the real work
smarty_modifier_capitalize_ucfirst(null, $uc_digits);
$string = preg_replace_callback(&#8217;!bw+b!&#8217;, &#8217;smarty_modifier_capitalize_ucfirst&#8217;, $string);
//restore the contractions and return
return str_replace($tmps,$apos,$string);
}

example.tpl:

<br /> {assign value=&#8221;max&#8217;s horse didn&#8217;t fall. &#8217;someone&#8217; is coming.  they&#8217;re here!&#8221; var=&#8221;capt&#8221;}<br /> {$capt|capitalize}<br />
Output:
Max’s Horse Didn’t Fall. ‘Someone’ Is Coming. They’re Here!

tags:

Nov 4

I can’t stand the way VBScript handles non-values.  Consider the following:


strValue = SomeFunction()

If strValue = &#8220;&#8221; Then
&#8216; Do Something
Else
&#8216; Do Something Else
End If


This fails unless your SomeFunction() function specifically returns an empty string, such as:


strValue = SomeFunction()

If strValue = &#8220;&#8221; Then
&#8216; Do Something
Else
&#8216; Do Something Else
End If

Function SomeFunction()
SomeFunction = &#8220;&#8221;
End Function


This is because even an empty string is considered a value in VBScript, on which you can check the length and check for IsEmpty().  However, this doesn’t work if your function returns a variable that has no value, like this:


strValue = SomeFunction()

If strValue = &#8220;&#8221; Then
&#8216; Do Something
Else
&#8216; Do Something Else
End If

Function SomeFunction()
strValue = SomeOtherFunction()
SomeFunction = strValue
End Function


In this case, if the SomeOtherFunction() did not return a value, then the value of strValue is NULL.  In VBScript, a NULL is defined as “no valid data.”  So, the only way to validate this variable is to check for NULL:


strValue = SomeFunction()

If IsNull(strValue) Then
&#8216; Do Something
Else
&#8216; Do Something Else
End If

Function SomeFunction()
strValue = SomeOtherFunction()
SomeFunction = strValue
End Function


Because strValue does not hold valid data, IsNull() evaluates to TRUE.  Now, in the case of objects, where you expect a function to return an object, you have to use a completely different method:


Set objValue = SomeFunction()

If objValue Is Nothing Then
&#8216; Do Something
Else
&#8216; Do Something Else
End If

Function SomeFunction()
Set objValue = SomeOtherFunction()
Set SomeFunction = objValue
End Function


Strange, and not entirely intuitive, but there it is…

Nov 4
Looks like the clever folks over at GrayHats.com have created a special version of Google for those who speaks the language of gamerz and h4×0rz:

These people have too much time on their hands. It is pretty funny though…

Nov 4

Apparently, Reno, Nevada has invested a lot of time and money to beautify the city. Recently though, “graffiti artists” (also known as street punks), have been adding their own brand of beautification to highway landscaping. When such vile crime occurs, drastic measures must be taken.

At least, according to Oscar Goodman, mayor of Reno.

Goodman suggested that these ultra-violent criminals have their thumbs cut off on live television. The mayor made these comments while appearing on a local television show “Nevada Newsmakers,” and also suggested a return to canings and whippings.

In 2004, the city reported 1,480 violent crimes, broken down as such:

  • 9 murders
  • 112 rapes
  • 464 robberies
  • 895 aggravated assaults

There were 10,154 property crimes, all falling under the categories of burglaries or thefts.

I wonder what the good mayor would suggest as punishment for the fine people who committed these crimes. So let’s hear it for another great idea from our politicians - clearly Reno, Nevada has got a handle on the best way to protect its citizens.

I’ll definitely be moving there next week…

Nov 3

One of my recent projects for a customer of mine, ResortScope, LLC, involved setting up some web services to allow access to data in our database to external consumers.  To provide this functionality, I used the NuSOAP library and PHP.  However, one of the limitations of the NuSOAP library is that it is unable to parse SOAP headers, which typically contain authentication information.  Consider:



<?xml version="1.0" encoding="utf-8"?>
<SOAP-ENV:Envelope
SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/"
xmlns:si="http://soapinterop.org/xsd">

<soap:Header>
<AuthenticationInfo xmlns="urn:MyService">
<username>test</username>
<password>1a232d4dg35</password>
</AuthenticationInfo>
</soap:Header>
<SOAP:Body>
<ns1:SomeMethod xmlns:ns1="urn:MyService">
<param1>foo</param1>
<param2>bar</param2>
</ns1:SomeMethod>
</SOAP:Body>
</SOAP-ENV:Envelope>

As you can see, the username and password are embedded in the SOAP:header.  So, to get at this data, you will need to parse the header yourself.  The way I chose to do this was to subclass the NuSOAP soap_server class and override the service method.



<?php
class MySoapServer extends soap_server
{
var $_objParser;

// Class constructor
function MySoapServer($wsdl=false)
{
// Create a new instance of the XML parser
$this->_objParser = new MyXMLParser();

// Call the parent constructor method and pass the WSDL flag to it
parent::soap_server($wsdl);

} // End Function

function service($data)
{
// Parse the xml message
$this->_objParser->setXMLData($data);

// Retrieve the authentication information from the xml message
$arrCredentials = $this->_objParser->getCredentials();

// Sanity check - did we get the credentials?
if(is_array($arrCredentials) &#038;&#038;
($arrCredentials[&#8217;username&#8217;] != &#8220;&#8221;) &#038;&#038;
($arrCredentials[&#8217;password&#8217;] != &#8220;&#8221;))
{
// Authenticate the user
$this->_intWSUserID = $this->_authenticate($arrCredentials);

// If authentication was successful, handle the rest of the message
if($this->_intWSUserID > 0)
{
parent::service($data);
}
else
{
// return a SOAP fault
}
}

} // End Function

function _authenticate($arrCredentials)
{
// Sanity check: did we get a valid array?
if(! is_array($arrCredentials))
{
// return a SOAP fault
}

// Handle your authentication code here.  I use a MySQL database for holding user data

} // End Function

} // End of Class
?>

In this above example, I deal with a class called “MyXMLParser”, which is an object that has methods for parsing XML data.  You could just as easily parse the data using native PHP methods.  As you can see, the AuthenticationInfo is parsed out of the SOAP message header, and the username and password are extracted and passed to the _authenticate() method.  How you choose to do your authentication is up to you.  In my case, I return the userID from the database for the authenticated user.  If and only if I get a userID back from the _authenticate() method do I call the service() method in the parent class.

Thanks to Scott Nichol for a great PHP library!

Technorati Tags: php nusoap SOAP