Archive for Programming

British PHP? Cheers!

british_php

Several minutes ago, one of the regular and long-term contributors to the PHP community, a gentleman by the name of Daevid Vincent, posted a link to a blog post on the PHP General mailing list. (Enough links yet? Hang on, there’s more to come.)

The blog post, If PHP Were British, was something I enjoyed — despite my apparently inferior dialect of English, the bastardized American version. So I figured, what the hell? We got the land (after we, as Redcoats, knocked off a few million of those pesky Indians), so why not offer a peace treaty in the form of a few lines or reworked PHP core?

After about fifteen minutes of work, the result: BPHP (lifted straight from their comments section). It’s based upon the latest stable of the 5.4 branch as of this writing (5.4.4), and has the changes requested specifically by the main article, as well as few other related changes. Nothing serious, but it shows that, yes, most Americans are willing to reach out and be friendly and helpful world citizens, regardless of how we may appear to the rest of the nations around the globe.

Want to give it a test drive? Go ahead and download it in .tar.gz or in .tar.bz2 format.

You’ll no doubt see errors and such, but have no fear — I have absolute no intention of supporting this release, nor providing bug fixes, or really even acknowledging that I did, in fact, spend several minutes of my evening doing this.

I should probably mention that I did this in my own free time (I have about an hour before another client is re-running on the ABC network TV show “Shark Tank,” and finished some other work ahead of time), and not as part of the PHP team. And of course, it is licensed under the actual PHP license, is intended only for entertainment purposes, and neither myself (acting alone) nor the PHP Group, community, or anyone else is responsible for any damage, incompatibilities, et cetera. Just in case there are any future BPHP users out there who are lawyers. ;-P

Happy Friday…. mates.

What The Heck Is World Environment Day?

Last Tuesday evening, with a large party/barbecue planned for the then-upcoming weekend, I found myself swamped once again with a combination of client projects and work needing to be done around the house.  Wishing I’d used my time more wisely that and the previous day, I had come up with an idea for something I was going to use as an internal organization system and self-motivator for completing more projects per week.  I’d hoped that, in the future (as it was too late at the time), I’d stay better focused.  My idea: a hyped-up TODO list for the week that needs to be 75% complete by each Wednesday, affording more time for spending with the family on the weekend.  I decided to call it (rather obviously) the Wednesday Challenge.

Because I’m a geek, I started building it out (in PHP, natch), with hooks to my office computer to display alerts on my desktop, SMS for text alerts throughout the day, and of course, email.  Eventually, I hoped, I’d hook it to the API for my Google Calendar as well.  The plan was, with enough reminders throughout the day, I’d be less susceptible to distractions leading to a complete derailing of my originally-planned schedule.  Obviously, I needed a domain name, too, because – who knows? – maybe friends or family would want to use the system, too.  So I opted for a simple version of my uninspired project name: wedchallenge.com.  I registered it that Tuesday night.

Enter actor Don Cheadle and fashion model Gisele.

I had noticed that I was getting a bunch of traffic on the domain, so I checked to see if perhaps the domain name had been a drop — that is, a domain which had once been registered, but then expired.  Oddly enough, it all seemed to be not only organic, but without referrals.  That meant it was being typed directly into the browser.  I puzzled over it for many, many seconds before I got sidetracked on something else.

Then, one evening, while preparing dinner, I happened to see a few commercials, thanks to the useless and skip-laden DVRs we have with DirecTV (that’s another story altogether).  One commercial caught my eye, not because of the content or the actors, but the domain: wedchallenge.org.  At first glance, I thought it was my own domain.  Then it clicked: that’s why I’m getting hits, and that’s exactly why it’s all type-in traffic.

The wedchallenge.org site has nothing to do with my little project.  Instead, theirs is actually WED Challenge — World Environment Day Challenge.  A campaign launched by the United Nations Environment Programme.  Apparently, it was held on 5 June, 2011, but ads were still being run on TV at least as recent as the 16th or 17th of the month.

So while I can’t offer any information, advice, or anything at all with regard to the WED Challenge, I can tell you that, if you came in here via wedchallenge.com, you should instead go to wedchallenge.org.  And while I find it a really odd coincidence, you can accept my half-hearted apology, I suppose, since you’re apparently not just all interested in my idea.  ;-P

Announcing the Release of the System Detonation Library for PHP

As discussed somewhat at length in a rapidly-devolving thread on the PHP General mailing list, I am in favor of a function that, when called, will initiate on the host system a self-destruct sequence.  Well, being a nice, sunny, spring Friday morning, I decided to offer just that:

Introducing the first public release of the System Detonation Library for PHP.

This useless extension provides one function with one purpose: to cause your server to explode.  Due to the obvious hazards involved, including (but not limited to) loss of hardware, limbs, and potentially life and liberty, this has only been tested on one single occasion, using a PC with Ubuntu 10.10 and a heavily-modified SVN version of PHP 5.3.6.  Thankfully, as the test was successful, there were no serious injuries.

Firstly, you may download the package here.

Second, as a very basic course on the compilation and installation of this unofficial PHP extension, here are some simple instructions for Linux users.  All others are on their own, and this may (read: probably) will not work anyway…. which is a shame, because I know plenty of Windows boxes that should have the right to self-destruct as well.

  1. Download the package above.
  2. Extract it: tar -zxf detonate-0.2.tar.gz
  3. Change to the newly-created directory where the files are located: cd detonate-0.2/
  4. Build the wrappers for your version of the Zend/PHP API: phpize (NOTE: on Ubuntu-built packages, this command may be: phpize5)
  5. Build the necessary makefiles for your system: ./configure –with-detonate
  6. Compile the code: make
  7. Install the binary (as root, or using sudo): make install
  8. Edit your php.ini to load the newly-installed extension by adding this line: extension=detonate.so
  9. If you plan to use it via the CLI, you’re done.  For use on the web, remember to reload/restart your web server.
  10. Create a basic PHP script with the following: <?php detonate(); ?>
  11. Check your insurance coverage.
  12. Run the script created in Step #10.

And that’s all there is to it.  Feel free to install this on all of your systems and use it as a replacement for exit or die() in your scripts.  Because, unlike die(), this function will absolutely get the point across, once and for all.

Replacing One Character In A String With A Random Character

Just an hour or so ago, Ron Piggot asked a question on the PHP General mailing list. The original question was how he could replace a single matching character in a string containing multiple matches with another random character.  I mocked up a working example in about five minutes or so.  It’s far from perfect, and not very elegant, but it’ll work as a starting point of reference.

The code I sent back in reply follows:


(Finally) Announcing the Public Release of FileConv for PHP

Almost exactly two years ago, on New Year’s Day, 2009, I sent an email describing a new PHP extension I’d finished, and was interested in submitting to the PECL repository. The package, entitled FileConv, would natively handle file conversion for line endings, back and forth, between *NIX (LF: \n) and DOS (CRLF: \r\n). At that time, Ilia Alshanetsky recommended that I also add Mac conversion (CR: \r). Legacy MacOS, that is, prior to becoming a sort of ClosedBSD, if you will.

Somehow, as often happens in our busy lives, I forgot to follow through with submitting it to the PECL repo. Last night I was using one of the functions and found a datestamp bug, where – in certain situations – it would give the converted file a date approximately 430,000 years in the future. That’s actually almost 253-times the estimated duration for the complete decomposition of a modern PC, which is figured to be a paltry 1,700 years. That said, once I patched the file and recompiled, I was reminded of my discontinued effort to release the code to the public as an open source package. Well, time to change that, I suppose.

So today, you can download the FileConv extension right here:
FileConv-2.2.6.tar.bz2 (7,073 bytes)
FileConv-2.2.6.tar.gz (6,636 bytes)
FileConv-2.2.6.zip (10,531 bytes)

MD5 Hashes:
– d6200f0693ae63f9cc3bb04083345816 FileConv-2.2.6.tar.bz2
– c2b0db478628e0a4e2ce66fb06d19593 FileConv-2.2.6.tar.gz
– b3ff103424e4be36151a1c5f9cadd58d FileConv-2.2.6.zip

SHA1 Hashes:
– 0521fdeaa8bfb250c8c50bc133b355872fa70cad FileConv-2.2.6.tar.bz2
– 08e2c361fc41f925d0b4aa3a0bbdd7e0884b24d6 FileConv-2.2.6.tar.gz
– 9eb9355555dd8e6e6b6b7f3dc7464c7a6107b187 FileConv-2.2.6.zip

Keep in mind: this has only been tested on Linux (CentOS, Mandriva, and Ubuntu), as I have neither the ability nor desire to play on Windows (but feel free to try it). In a future release, the code will be compacted more, as well; right now, every conversion function has its own function within the source. This isn’t necessary: it could be a single master function with a simple switch for one small section of the code. I’ll get to that another day, when I have some time to hack it up again.

This distribution comes with a very simple automated installer for now. If/when it moves to PECL, that will be phased out, of course, as PECL will handle that itself. If you have root/sudo access on the box, you can just run ./install.sh from the package directory and follow the instructions from there. Manual installation instructions are included as well.

This package provides functions that somehow never made it into the PHP core: dos2unix(), unix2dos(), mac2unix(), mac2dos(), unix2mac(), and dos2mac(). It does not, however, do any checking or validation prior to conversion. If you decide to use this library, I’d highly recommend employing some basic checking in your code. Something like this should be used at a minimum:

<?php
function get_info($filename) {
  if (!function_exists('version_compare') || version_compare(phpversion(),'5.3.0','<')) {
    return trim(`file {$filename}`);
  } else {
    $finfo = finfo_open();
    $format = finfo_file($finfo, $filename);
    finfo_close($finfo);
    return $format;
  }
}

if (strpos(strtolower(get_info($filename)),' crlf line')) {
    // File is DOS (\r\n)
} elseif (strpos(strtolower(get_info($filename)),' cr line')) {
    // File is legacy Mac (\r)
} else {
    // File is *NIX (\n)
}
?>

NOTE: this does not ensure that it is a text file. You are strongly advised to address that as well. The included test.php file has a line that checks to see if the file is binary or text, so feel free to plagiarize that — or, better yet, build a better mousetrap.

If you come across any bugs/issues/whatever, let me know.

Skype and Google Earth Causes X To Crash On Ubuntu 10.10

[UPDATED 19-JAN-2010 – Thanks to Drew (in the comments) for bringing up the fact that this is only for 64-bit versions of Ubuntu. The filenames would indicate that, but no sense wasting your time if you’re looking for a 32-bit solution. Well, at least not yet. I may do a 32-bit build if there’s a need, but it seems as though the official repos may now have the patched versions. Have you gotten an official solution that resolved the issues? Feel free to let me know in the comments.]

After months of dealing with the mouse getting stuck between monitors, blinking like crazy and freezing all but remote SSH administration of my Ubuntu 10.04 (Lucid) desktop with triple-head monitor setup, I gave up and upgraded to 10.10 (Maverick) in hopes that it would fix the issues. I didn’t know if it did or not, because it introduced new errors. Worst of all: any time I would launch Skype, the screens would go black and X would crash in a segfault and restart. The same was true of Google Earth and of at least all Qt applications on the desktop. It took a good thirty-six hours before I traced everything back and came up with a solution. So now I’m running 10.10, which not only has a couple of minor improvements, but also seems to have finally fixed the mouse-locking issue. Hooray!

My issue turned out to be rooted in an issue with Xinerama on X with multiple monitors on an x86_64 box running the final stable of Ubuntu 10.10 (Maverick). If you have the same issues (Skype crashes X), try downloading the following file (routed through my company’s URL service so that it’s easier to share):

http://links.parasane.net/fvsq

The filename is xorg_crash_fix_debs_and_NVIDIA_driver_x86_64.tar.bz2, with the following hashes:

MD5: fe2fa5684a0f051d552bd7d0b4ee6f6a
SHA1: 0edea79d4832ce31954e29991405a67403732639

Applying it is simple (provided you have experience in knowing how to resolve your own dependencies, if any are missing). If you’d like to nip it in the bud before getting started, here’s an all-inclusive list of all packages of which I’m aware that you should have installed or which may be needed to finish this process without errors (feel free to pick and choose on your own, if you’re more comfortable doing a minimalist installation):

sudo apt-get install debhelper quilt bison flex xutils-dev x11proto-bigreqs-dev x11proto-composite-dev x11proto-damage-dev x11proto-xinerama-dev x11proto-randr-dev x11proto-record-dev x11proto-render-dev x11proto-resource-dev x11proto-scrnsaver-dev x11proto-video-dev x11proto-xcmisc-dev x11proto-xf86bigfont-dev x11proto-xf86dga-dev x11proto-xf86vidmode-dev x11proto-dri2-dev libxfont-dev libxkbfile-dev libpixman-1-dev libpciaccess-dev libgcrypt-dev nettle-dev libudev-dev libselinux1-dev x11proto-xf86dri-dev x11proto-gl-dev libxmuu-dev libxrender-dev libxi-dev x11proto-dmx-dev libdmx-dev libxpm-dev libxaw7-dev libxmu-dev libxtst-dev libxres-dev libxv-dev libxinerama-dev devscripts build-dep xserver-xorg-core

The steps to installing the fixed binaries are:

  • Drop to an alternative TTY prompt: Press CTRL+ALT+F1
  • Download the package file: wget http://links.parasane.net/fvsq -O xorg_crash_fix_debs_and_NVIDIA_driver_x86_64.tar.bz2
  • Uninstall your current NVIDIA drivers: sudo nvidia-uninstall
  • Decompress the file linked above: tar -xjvf xorg_crash_fix_debs_and_NVIDIA_driver_x86_64.tar.bz2
  • Change to the newly-created directory: cd xorg_crash_fix_debs_and_NVIDIA_driver_x86_64/
  • Install the core and common packages: sudo dpkg -i xserver-xorg-core_1.9.0-0ubuntu7_amd64.deb xserver-common_1.9.0-0ubuntu7_all.deb xvfb_1.9.0-0ubuntu7_amd64.deb
  • Set execution permissions on the included NVIDIA driver: chmod 0755 ./NVIDIA-Linux-x86_64-260.19.21.run
  • Execute the new NVIDIA driver: sudo ./NVIDIA-Linux-x86_64-260.19.21.run
  • Reboot the system: sudo shutdown -r now

You should now have a fully-working X system again. And if you upgraded because of the mouse-hang issues, you should be in good shape there, too!

NOTE: It should be VERY obvious, but this comes with absolutely no warranty or guarantee whatsoever, and you’re completely responsible for any issues that arise, directly and/or indirectly, from usage of these packages or instructions, et cetera. You know the drill by now, I’m sure.

JavaScript In Smarty

Just before I gave up with Serendipity – which uses the Smarty templating engine – I was trying to add some Google Analytics code into the template.  Because GA creates an anonymous function in JavaScript, instead of simply including the remote JS source file (which does make sense, in reality), it includes curly braces — and Smarty hates that.  It prompted me with errors about unknown tags and stuff.  Hooray.

Well, thankfully, the fix was simple: wrap the JavaScript code in ‘literal’ tags.  Example:


{literal}
<script language="JavaScript">
alert('Smarty takes this literally.');
</script>
{/literal}

Goodbye, s9y!

I’d finally had it.

Serendipity had a bunch of issues that were interruptive at best — destructive at worst.  I know plenty of other people have had success and been quite pleased with it, but it just wasn’t the right fit for me.  I’d known it for some time, but let’s face it: unless you’re a “blogger” by trade, you probably have more important things to do than update your personal hobby site.  I fell right into that camp myself.  I just couldn’t be bothered trying to convert it to something else.

Enter: WordPress.

Through one of my companies, PilotPig Web Hosting, we frequently get hosting orders for WordPress sites.  So the account is created, activated, and WordPress is installed for the customer.  I’ve done literally a few hundred installations and some basic customizations of the package, but I’ve never actually used it myself — until right now.  Seems decent.

Well, the one problem I thought I’d be facing was getting the posts from Serendipity imported into WordPress.  I was wrong.  All I needed to do was grab the full RSS 2.0 feed from s9y (/rss.php?version=2.0&all=1), save it to my Desktop, then run it through a quick conversion script that took all of two minutes to write:
<?php
if (!isset($argv[1])) {
echo 'Enter the RSS feed file to convert: ';
$argv[1] = trim(fread(STDIN,128));
}

$data = file_get_contents(dirname(__FILE__).DIRECTORY_SEPARATOR.$argv[1]);

file_put_contents(dirname(__FILE__).DIRECTORY_SEPARATOR.$argv[1].'-converted',
htmlspecialchars_decode($data,ENT_QUOTES));

Then just import it using the WordPress RSS importer tool, and – ta-da! – my work here was done, and I could go back to my day.  Neat.

ImageMagick `convert` 100% CPU Usage

Plain and simple: upgrade to the latest, if necessary, and compile with the flag:

–disable-openmp

Flashy and complicated: if you’re on CentOS5, specifically, you can do what I needed to do. I needed to write a patch for a client’s network of systems. You don’t need to do that, though, unless you need OpenMP on there (which you probably don’t). Wish I’d realized that was the issue before I went hog-wild.

So if you’re running into an issue where the ‘convert’ command is using 100% of your CPU (we had it running 800% — 100% x 8 cores), try the above. Most likely, that’ll fix ‘er.

Add New Domains to Apache On Command Line

I had a need to add several domains to Apache for a client about an hour ago, and instead of copying, pasting, changing, and repeating, I opted to script it. It’s very simple (read: not secure for multiple users in production), but served my needs today beautifully. Feel free to clean it up and use it, change it, whatever.

The primary reason this is added is to show how CLI scripts can be made to wait for and accept user input. Note the use of STDOUT and STDIN in the script. This is something that I’ve found to be quite unfortunately overlooked in a lot of CLI scripts. Using this, you can make a PHP CLI script interactive, instead of requiring arguments to be passed on the command line.

Also, note that this particular script wasn’t needed for user creation, DNS, or anything of the like. Strictly for adding an Apache directive for the domain.

(The code itself is indented, but I’m learning more and more why Philip Olsen scoffed at me for installing Serendipity last year. Eventually my error in judgment shall be rectified.)


#!/usr/bin/php
<?php

if(trim(`whoami`) != 'root') die("You must be root to run this command.\n");

fwrite(STDOUT,"Domain to be added: ");
$domain = trim(fgets(STDIN));

fwrite(STDOUT,"Username to use for this domain: ");
$user = trim(fgets(STDIN));

fwrite(STDOUT,"Group to use for this domain: ");
$group = trim(fgets(STDIN));

fwrite(STDOUT,"Path to use for the web root of this domain: ");
$path = trim(fgets(STDIN));

fwrite(STDOUT,"Server administrator's email address to use: ");
$email = trim(fgets(STDIN));

echo "Writing.... ";

$newHost =<<<TXT

NameVirtualHost *:80
<VirtualHost *:80>
ServerAdmin $email
DocumentRoot $path
ServerName $domain
ServerAlias www.$domain
ErrorLog logs/$domain-error_log
CustomLog logs/$domain-access_log combined
<IfModule mod_suphp.c>
suPHP_Engine On
suPHP_ConfigPath "/etc/"
suPHP_AddHandler x-httpd-php
suPHP_AddHandler php5-script .php
suPHP_UserGroup $user $group
</IfModule>
</VirtualHost>
TXT;

file_put_contents('/etc/httpd/conf/httpd.conf',$newHost,FILE_APPEND);

echo "Done.\n";

fwrite(STDOUT,"Should I restart Apache now for the changes to take effect? (y/N) ");
if(preg_match('/^ye?s?$/i',trim(fgets(STDIN)))) {
exec('service httpd restart');
echo "Apache restarted.\n";
}

?>