went-green-to-support-iran.jpgFolks on Twitter recently introduced me to a new movement (ehh, fad): adding a bright green overlay to your avatar as a sign of support for free and open democratic elections in Iran.  So, yes, I thoroughly dislike Mahmoud Ahmadinejad, and yes, I do think that the recent election in Iran was a complete joke.  In Twitter hash-tag speak, one might even call it a total #electionfail.  And for the record, no, I don't support any other candidate or political party in Iran.  All I'm interested in is Iran opening itself up so the Iranian people can actually elect a President that won't continue to drive the country into the ground.

Want to join the club?  You can make your own green Twitter avatar here.  Or, you can do it yourself using a tool like Photoshop CS3: Image->Adjustments->Black and White.  Click Tint, and adjust the Hue and Saturation sliders until you have a nice green glow.

Here's a screenshot.
Gagawa PHP 1.1-beta has been released on Google Code.  This version contains an important fix for a single issue, which was reported here on May 23rd.

In version 1.0, Gagawa uses empty() to check for valid arguments inside of the Attribute, Node, and FertileNode classes.  If the user tried to add an attribute with a value of "0" (zero) PHP's empty() function returned true and Gagawa threw an Exception claiming the attribute value was empty.  Well, in some cases you might need an element with an attribute value of zero, like so:

<div foo="0">bar</div>

This is completely legit.  As it turns out, the empty() function considers the following "things" to be empty:

  • "" (an empty string)
  • 0 (zero as an integer)
  • "0" (zero as a string)
  • NULL
  • FALSE
  • array() (an empty array)
  • var $var (a variable declared but without value)

However, in Gagawa's case the string "0" isn't empty, it's a valid value so empty() isn't the right check.  The solution was to add a GagawaUtil::gagawaEmpty() function that has some special logic in it to check incoming attributes and tag types.  This new gagawaEmpty() function is a modified version of code borrowed from here from PHP.net.

Enjoy.
In some Apache web-server configurations, it might be useful avoid logging requests from specific IP addresses or User-Agents.  For example, if you regularly check your own site from your home network you probably don't want to record your own visit in your Apache access_log's.  For kolich.com, I stopped logging requests from my home network since I was filling up my own log files with redundant junk.

1 - httpd.conf Specific Configuration

Here's how you can stop logging requests from a specific IP address, or a request for a specific resource (goes in your httpd.conf file):

## Dont log myself (requests from my own network), requests
## for my robots.txt file.
SetEnvIf Remote_Addr "192\.168\.1\." dontlog
SetEnvIf Request_URI "^/robots\.txt$" dontlog

## I don't use this, but I have it here as an example. Why
## I avoid using this is explained below.
##SetEnvIfNoCase User-Agent "(msnbot|googlebot|slurp)" dontlog

## Normal logging directives. Note the env!=dontlog at the
## end of CustomLog.
ErrorLog logs/mark.kolich.com-error_log
CustomLog logs/mark.kolich.com-access_log combined env=!dontlog

2 - Why Should I NOT Use SetEnvIfNoCase User-Agent to Avoid Logging Requests From Specific User-Agents?

You can use "SetEnvIfNoCase User-Agent" if you want to stop logging requests from specific User-Agent's.  However, I would recommend that you avoid using this feature because it is extremely easy to forge/fake the User-Agent header of an HTTP request.  If a hacker tries to probe or attack your site disguised as the "GoogleBot", and your Apache server is configured to not log requests from clients that claim they are the "GoogleBot", you won't see the probe attacks in your log files.  Apache will think the request is from the GoogleBot, when in fact, it could be a hacker or malicious user masquerading as a web-crawler.

Cheers.
There are an endless number of ways to parse and validate GET or POST inputs to a PHP script.  I've seen examples (and have written code) that use everything from array_key_exists to empty to preg_match.  In any event, there doesn't appear to be a standard way of parsing and validating form inputs from a GET or a POST; each developer and application seems to use its own validation mechanism.  So, what is the PHP community preferred way to safely and securely validate submitted formvars?  I don't know.  But, I think I personally use a pretty robust and secure method for validating GET and POST form inputs in PHP.  So, consider this post an attempt to document and explain what I use in PHP to securely parse, filter, and validate formvars from a GET or POST.

For form validation, assuming you're running PHP 5.2.0 or greater, you really can't do much better than PHP's very own filter_input_array function.  If you're not familiar with filter_input_array, you should look into it.  From php.net, filter_input_array "...gets external variables and optionally filters them."  In other words, filter_input_array gives you a lot parsing and validation logic for free.  It avoids the need to manually walk through each element of $_POST[], check if it exists, etc.  And for an AJAX controller (a handler) written in PHP, filter_input_array can be very helpful.

Continue reading for some examples ...
helpful-shot.pngYesterday I received a really appreciative email message from someone who enjoyed my post on converting .caf files to .mp3's.  The sender stated she has a friend who recently lost a close family member.  The friend had saved several voice mails from the deceased on her iPhone, and wanted to save the voice mail audio files as a remembrance.  With the information found on my post, everything worked out great: the friend extracted the .caf files from the iPhone and successfully converted them to an .mp3, and I got a nice email praising my blog!

This was clearly a special case, but it got me thinking that I might be able to make it easier for people to give me a general thumbs-up or thumbs-down for each of my blog posts.  For a number of reasons, I don't accept comments on my blog so this is the next best thing.  I accept comments on my blog as of 7/2/09.

php-comparison-operators-quick-reference-screenshot.pngI've been working on a lot of PHP lately, and found myself looking at php.net's Comparison Operators reference quite a bit.  Since I was tired of sorting through the details at php.net, I put together a minimal quick reference guide.  Basically, this guide is an enhanced copy+paste of the tables found on php.net's Comparion Operators page, just without all of the distractions and examples.

The HTML version of the quick reference card is here.  Or, you might want the PDF version for easy printing.

Eventually, I hope to make a more complete PHP quick reference card that shows operator precedence, arithmetic operators, bitwise operators, etc. all on a single page.  Stay tuned ...

Enjoy.
If you're ever in a situation where you need to generate a cryptographically strong random number, then you might be interested in learning a little more about Java's java.security.SecureRandom. So, what's the difference between java.util.Random and java.security.SecureRandom?  Well, SecureRandom is special because it aims to make it more difficult to programatically predict the next random number in a sequence.  And, not surprisingly, guessing or predicting random numbers in an insecure random sequence is trivial.  So, any crypto-based code that requires a random number for digital signature generation, session key generation, etc., should always use SecureRandom.
alternating-rows-after.pngIn any web-application, there are always a few trivial and seemingly mundane enhancements the developer can implement that add significant value for the end-user.  And with the right tools in hand, implementing these enhancements can be down right simple.  Take alternating gray rows in a table for instance, or a slick mouseover highlighting effect when the user moves their mouse cursor over each row in a table.  Not surprisingly, you can easily implement these quick enhancements using jQuery.

A complete example can be found here, or continue reading for some screen shots.

twitter-logo.pngI recently stumbled across this awesome post via Twitter that explains how to Tweet from the command line like a pro using curl.  I tried it, and sure enough, it works!  If you want to Tweet a message from the command line using curl, here's how:

#/> curl -u mytwitterusername:mypassword \
-d status="from the cmd line!" \
http://twitter.com/statuses/update.json

Even cooler, if you want to pipe output into a Tweet (like your system uptime from the "uptime" command), you can run the following:

#/> curl -u mytwitterusername:mypassword \
-d status="my uptime:`uptime`" \
http://twitter.com/statuses/update.json

Note that if you are behind a corporate firewall at work, you will need to tell curl to use an HTTP web-proxy to communicate with the outside world.  This can be done using the -x option like so:

#/> curl -u mytwitterusername:mypassword \
-d status="from the cmd line!" \
-x web-proxy.example.com:8088 \
http://twitter.com/statuses/update.json

Or, if you wanted to pipe the output of a command into a Tweet, you can do so using the -d @- arguments which asks curl to read the POST input from <STDIN>.  Here's an example of piping the output of "df -h /" into a Tweet (to Tweet the usage of my root disk):

#/> echo "status=`df -h /`" | \
curl -u mytwitterusername:mypassword \
-d @- \
-x web-proxy.example.com:8088 \
http://twitter.com/statuses/update.json

For the HP-UX Tweeps out there (@HP_UX) ...

If you happen to be using a system without curl, you can easily install it.  On HP-UX, curl can be installed using the HP-UX 11i Internet Express package available from hp.com (HP-UX 11i v2 or HP-UX 11i v3).  As root on your HP-UX box, use the swinstall command to install your freshly downloaded .depot ...

swinstall -s /path/to/depot/internet_A.12.00.013_HP-UX_B.11.23_IA_PA.depot

Enjoy!
Thumbnail image for datacenter.jpgSeveral days ago I spent more than 5 hours setting up a fresh install of Windows Vista Enterprise on a desktop computer in my home office.  This setup process involved tweaking the system configuration, installing and configuring all of my required software for development, checking out a massive SVN code repository, etc.  Sadly, less than a week after I finished setting up this box, the SATA hard disk died.  As it turns out, the disk flat out overheated due to poor airflow around the disk chassis in my PC (that's a story/post/opinion piece for another day).  In short, I lost everything on the drive.  All of the blood, sweat and tears; for nothing.

I decided to never let this happen again (since it's a huge time suck sitting around waiting for software to install) and began investigating free, yet solid and reliable backup solutions suitable for a home office.  This post is an attempt to document what whole disk backup and recovery solution worked for me, using several freely available open-source tools.

NOTE: This backup and restore procedure has worked for me twice as of 6/11/09.  See the FOLLOWUP in red at the bottom of this post for details.