Export Symphony CMS Blueprint metadata

Symphony is a powerful CMS system that is used by many of the world’s most recognisable brands. It’s a great system that lets the developer focus on XHTML and data they are creating rather than much of the back-end code. It does have it’s flaws though and one of them is that it’s very easy for Symphony ‘sections’ and ‘pages’ to get out of sync between production and staging servers.

Sure, the pages themselves can be version-controlled but much of the metadata about the pages such as which datasources are attached are stored in the database and previously this data was only really accessible by clicking on each page within Symphony individually. Now this is fine if you have just a couple of pages but on some of the sites I’ve worked on this involved 50 pages or more with almost as many sections…

My solution was to create a Symphony extension called Blueprint Metadata that pulled this metadata out of the database and export it as an XML file conveniently time-stamped containing the server hostname. This allows you to quickly ‘diff’ the changes between two servers and quickly see the differences so you can apply them manually. I wrote this extension quite a few years ago but still find myself using this even today and have decided to make it open source under a very flexible BSD license.

Feel free to grab the Blueprint Metadata extension on Github now.

Installing Xdebug on Mac OS X

Xdebug is an incredibly powerful PHP extension that helps you debug scripts by providing a lot of valuable debugging information. It saves you from having to write your own debugging function for catching errors, at least during the development stage of a web application and certainly provides a lot more information than the standard PHP error messages!

Xdebug also provides the following: –

  • Stack traces and function traces in error messages with:
    • Full parameter display for user defined functions
    • Function name, file name and line indications
  • Support for member functions
  • Memory allocation
  • Protection for infinite recursions
  • Profiling information for PHP scripts
  • Code coverage analysis
  • Capabilities to debug your scripts interactively with a debug client

From the above you can see it’s a very powerful tool that every web developer should have installed on his or her machine and is in-fact included with quite a few commercial IDE programs. Surprisingly, Xdebug is actually open-source, so without further ado… I’ll show you how you can easily install it on your Apple Mac using pre-built binaries

Equipment

This tutorial assumes you have the following already set up: –

  • Apple Mac OS 10.4
  • Apache (Using Apple’s version that came with OS X)
  • PHP 5 Module (I use PHP 5 from www.entropy.ch)
  • Some PHP files you can test and debug with

Instructions

Xdebug doesn’t provide any pre-built binaries for Mac OS X, which means we would have to download the source code and compile Xdebug ourselves. Luckily a commercial IDE called Komodo IDE (made by ActiveState who you might remember as the company that makes Perl for Windows), distributes Xdebug with their program and have kindly made their Xdebug binaries available for download. Navigate to the remote debugging page on their website and click on the PHP Remote Debugging option. Make sure you choose Mac OS X / x86 if you have an Intel Mac.
Once downloaded, extract the contents and click on the folder corresponding to your PHP version (I chose 5.2). You should see a single file called xdebug.so. This is our PHP extension… drag it into your user folder.

Now we need to copy the extension into our PHP extensions folder. Drop into the Terminal application and if you used the Entropy PHP 5 extension, you’ll find the PHP folder at /usr/local/php5. The extensions folder is in lib/php/extensions.

At the terminal type:

cd /usr/local/php5/lib/php/extensions

List the contents and you should see a folder called no-debug-non-zts-20060613 or similar, change directory into here. We’ll now move the xdebug.so file into this folder and rename it xdebug. Note: You’ll get prompted for your password since we’re editing system files.

ls
cd no-debug-non-zts-20060613
sudo mv ~/xdebug.so xdebug

Nearly there, we now need to create an .ini file to tell PHP to load in the extension. Change directory to /usr/local/php5/php.d and using vi or your favourite editor create a file called 80-extension-xdebug.ini. Note: You’ll get prompted for your password since we’re editing system files.

cd /usr/local/php5/php.d
sudo vi 80-extension-xdebug.ini

Copy and paste the following into the text file you’ve just created, adjusting the path to where your extensions directory is located.

[xdebug]
zend_extension="/usr/local/php5/lib/php/extensions/no-debug-non-zts-20060613/xdebug"

If you have TextMate, you can add the following line to the config file. This makes clickable error messages that load up the offending PHP file in TextMate and jump to the line containing the error. This is very handy indeed!

xdebug.file_link_format = "txmt://open?url=file://%f&line=%l"

Once your ready to save the config file, close vi by typing ‘:x’ followed by the return key. Restart Apache using your favourite method or simply reboot the whole machine.
Test your new Xdebug configuration by creating a PHP file, which obviously has an error in it such as calling a function that doesn’t exist. Test the PHP file and you should see a lovely coloured error message with a stack trace! You’re all ready to go!

Extras

If you’re interested in getting the most out of Xdebug, I recommend checking out some of the documentation on the Xdebug site. Of particular interest is using the profiler and the basics, which are always good to master.

Problem with PHP mail() and Additional Headers

With the PHP mail() function, you can specify additional headers for the emails that you send. This is a very powerful feature, which lets you do things such as add addresses to blind carbon copy or specify which email address the email is coming from.

It’s great but the PHP manual says this about additional headers: –

additional_headers (optional)

String to be inserted at the end of the email header.

This is typically used to add extra headers (From, Cc, and Bcc). Multiple extra headers should be separated with a CRLF (\r\n).

Yes, so according to the manual multiple headers should be separated with CRLF (\r\n). However, if you try this on a Linux web server (sample code provided below) you will probably get some of your headers stuck in the body of the email! There is a quick and easy solution though…

// Recipient
$to = '[email protected]';

// Subject of email
$subject = 'Message from Eddie';

// Message body
$message = 'Hi there, this is Eddie, and I\'m feeling just
great, guys, and I know I\'m just going to get a bundle of kicks out of any
programme you care to run through me';

// Additional headers
$headers = 'To: [email protected]' . "\r\n";
$headers .= 'From: [email protected]' . "\r\n";

// Mail it
if(mail($to, $subject, $message, $headers)) {
echo 'Email sent';
} else {
	echo 'Email not sent';
}

Apparently on Linux web servers, it’s best to use LF (\n) line endings for separating headers instead. This can be done two ways. The first way is to alter the server’s sendmail path in PHP.ini file to first push the email through dos2unix (which converts the line endings automatically) and then pipe it to send mail.

sendmail_path = "/usr/bin/dos2unix | /usr/sbin/sendmail -t -i"

The other option is to alter your PHP code so that instead of appending the line endings on as strings use the PHP_EOL constant which was introduced in PHP 5.0.2. Echoing PHP_EOL on a Windows server will result in “\r\n” whilst echoing the constant on a Linux server will result in “\n”… which in my opinion is a more elegant solution. :)

The Secret to cURL in PHP on Windows…

cURL is a great library created by Daniel Stenberg, that allows you to connect and communicate to many different types of servers using many different types of protocols. In particular, it’s used heavily in PHP to communicate to Payment Gateways and fetch XML feeds from other sites whilst being ‘transparent’ to web page visitors.

The particular secret I would like to share involves establishing connections to secure sites (SSL-enabled ones in particular). When you browse to an SSL–enabled site in your web browser, a few things happen… One of the things that happen is that your browser checks to see if the site’s security certificate is trusted. It does this by checking the entity that signed the certificate against it’s built in book of trusted signatures and if it finds a match, onto the next step. However, if your browser can’t find a match the certificate will be invalid and it will complain that the site could potentially be a fake or insecure.

The ‘book of trusted signatures’ is known as a Certificate Authority bundle and usually comes built in with most web browsers. If you install cURL (the standalone version that can be run from the command–line), chances are it will come with the cURL Certificate Authority bundle and you won’t need to do a thing as the cURL functions within PHP will use this as it’s book of trusted signatures. However, on Windows the cURL functions within PHP are pre–built and included in the standard PHP setup, thus do not include this bundle. Chances are if you don’t know this you’ll probably spend a good amount of your time screaming at your webpage as it mocks you with error number 60! I know I spent quite a good few hours wondering why it worked on my Linux PC but not on the Windows server!

CURL Error 60: SSL certificate problem, verify that the CA cert is OK.
Details: error:14090086:SSL routines
SSL3_GET_SERVER_CERTIFICATE:certificate verify failed

Luckily the fix is quite easy…

  1. Download standalone cURL for Windows (make sure it is the SSL version).
    Download the .pem file from the cURL site and rename the extension to .crt
  2. Extract curl-ca-bundle.crt from the download and copy to your web server folder.
  3. Add the following line to your code: –
    curl_setopt($ch, CURLOPT_CAINFO, "c:/path/to/ca-bundle.crt");
  4. Remember to change $ch to the variable you’ve assigned your curl connection to and “c:/path/to/ca-bundle.crt” to the location of where you have copied the ca-bundle.crt.
  5. Check the server has permission to read this file.

If you are getting started with cURL, here is some sample code I’ve written that should get you started. It outputs the contents of the secure server to a string, which is echoed out to your page.

// Set up cURL connection
$url = 'https://www.verisign.com/';
$ca = 'c:/path/to/ca-bundle.crt';
$ch = curl_init();

// Apply various settings
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_HEADER, 0); // Don’t return the header, just the html
curl_setopt($ch, CURLOPT_CAINFO, $ca); // Set the location of the CA-bundle
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); // Return contents as a string

$result = curl_exec ($ch);
curl_close($ch);
echo $result;

That’s it! You should now be able to connect successfully to SSL-enabled websites using the cURL functions of PHP on your Windows server.

UPDATE 2010/08/20: Apparently the certificates aren’t shipped with the archived versions any more. To get the latest certificate bundle that’s been extracted from the Mozilla browser you can download the .pem file from the cURL site and rename the extension to .crt.

Validating Credit Card Numbers

Lately, I’ve been working on an e–commerce website and discovered a handy algorithm for validating card numbers. The Luhn algorithm (also known as mod 10) is a checksum formula and is used to protect against accidental errors rather than malicious attacks.

The algorithm is particularly useful for checking to see if the card number ‘looks’ right before sending it off to the payment provider for processing. This reduces the amount of rejected card payments, which is always a good thing. :)

More details of how the algorithm works can be found on Wikipedia and my annotated PHP implementation can be found below.

/* PHP function for validating card numbers */
function checkLuhn($cardNumber) {
    // Copyright (c) Richard Warrender. Licenced under the LGPL.
    // https://richardwarrender.com//

    // Get total amount of digits to process
    $digitCount = strlen((String) $cardNumber);
    // Checksum must be zero to begin with
    $checksum = 0;

    // Loop round card number extracting digits
    for($i = 1; $i<=$digitCount; $i++) {
            // Extract digit number
            $digits[$i] = (int) substr($cardNumber, -$i, 1);

            // Check to see if this the luhn number, we need to double it
            if(($i%2) == 0) {
                    // Double luhn digit
                    $digit = $digits[$i] * 2;

                    // If greater or equal to 10, then use sum of digits
                    if($digit >= 10) {
                            // Get first digit
                            $firstDigit = substr($digit, 0, 1);
                            // Get second digit
                            $secondDigit = substr($digit, 1, 1);
                            /// Add together and replace original luhn digit
                            $digit = $firstDigit + $secondDigit;
                    }

                    // Reload back into array
                    $digits[$i] = $digit;
            }
            // Keep a running total for use in checksum
            $checksum += $digits[$i];
    }

    if(($checksum % 10) == 0) {
            return true;
    } else {
            return false;
    }
}