Featured Posts

18Jul2010

I recently had a friend call me in need of computer repair assistance. I’ll save you the many hours of troubleshooting and simply list the fix here.

The Dreaded crcdisk.sys

I found this symptom of the problem by booting into Safe Mode and watching the drivers load. I noticed that it always hung for a long time on the crcdisk.sys file. Well, if you perform a search on Google for “windows vista crcdisk.sys” you will find a plethora of woes from computer users desperately trying to regain the functionality of their PC. There are also a plethora of fixes, advice and this worked for me posts. I tried many of these to no avail.

The Road To Recovery

The laptop I was working on was a Toshiba laptop and it had a system restore disk. Great! Sort of. Restoring the system to factory condition from the disk (after the owner had backed up their data of course) resulted in a system that was broken and still had the problem listed above. Hmmm.

Another operating system perhaps? I installed Windows XP from scratch. Worked great. I installed Windows Vista SP2 from scratch (another disk). Worked great. Re-tried the system restore from Toshiba. No good.

At this point I figured I was just going to install Vista from scratch. So I reinstalled Vista and downloaded the Toshiba drivers from their website. One by one I started installing the drivers. Until I got to the driver for a flash media card reader (front of laptop). Bam! It froze up during the install. So I rolled that change back using Windows System Restore and then continued with all of the other drivers. No problems. I tried the flash media driver one more time just to be sure, and sure enough it failed again. That’s good! Predictability is key in diagnosing computer problems.

The Solution

So now I knew that the flash media card reader was probably bad, and so when the drivers were applied it froze the system. I unzipped the driver distribution and made a list of the files in it. Then I went back and restored the system from the Toshiba system restore disk. I did NOT however, reboot and continue the installation. I rebooted to a Windows system disk and brought up the recovery console (command prompt). I then went into the Windows directory (C:\Windows) and deleted ALL of the files that I had listed from the flash media card driver. One reboot later and the system was continuing the installation all the way to success.

Suggestions

SO… what does this say about our crcdisk.sys error? Absolutely nothing! Well, almost. It makes sense (to me at least) because the system was trying to access a disk and it was failing, thus the “disk” part of crcdisk.sys. So my suggestion for solving the above problem would be to put your troubleshooting hat on. You can try the steps above or one of the many that you’ll find on the internet, but keep this in mind. Just make one small change at a time until you find something that makes a difference. That should give you some good clues as to the root of the problem.




16Jul2010

The Problem

I was recently working on a project that is built on WordPress / BuddyPress. I built up some content using the CMS features of WordPress in my development server and then I transfered the WordPress content to a beta server using the export/import functionality. That kind of stinks having to do that every time I want to push updates to my beta server. So I looked into using Doctrine to generate data fixtures which I could repeatedly run against the different database. Doctrine supports YAML files, which are extremely easy to edit by hand, so it seemed like a good idea.

So what’s the problem? Well, I didn’t currently have any of my data in YAML files. I didn’t want to had edit them or do some sort of copy and paste madness. So, I wrote a script in PHP to dump my data into a YAML file.

The Solution

I’m not going to do much explanation because the code is fairly well commented. You can download the file here or you could just copy and paste it from below, but you may get some weird character conversions. The script can generate YAML for all the tables in your database, for a specific list of tables or you can specify an SQL query. Just execute the script without any arguments to see the usage statement (or just read it at the top of the file). Without further ado, here’s the script.

#!/usr/bin/env php
<?php
/* ========================================================
 * File           : dumpyaml.php
 * Date           : July 15, 2010
 * Author         : Jonathan Franzone
 * Author Website : http://www.franzone.com
 *
 * Script to generate YAML (http://www.yaml.org/) from
 * a MySQL database. Will generate YAML for either all
 * tables in the specified database, only the specified
 * tables in the specified database or only the given
 * SQL query.
 * ========================================================
 */
 
/* ========================================================
 * Configuration (read from command-line)
 * ========================================================
 */
$DBHOST = '';
$DBUSER = '';
$DBPASS = '';
$DBNAME = '';
$TABLES = array();
$DBQUERY = '';
$QUERYNAME = '';
$CONVERT_NAME = false;
 
/**
 * Prints the usage for this script
 */
function usage() {
  echo "
MySQLToYaml [Jonathan Franzone; http://www.franzone.com]
 
  Script to generate YAML (http://www.yaml.org/) from
  a MySQL database. Will generate YAML for either all
  tables in the specified database, only the specified
  tables in the specified database or only the given
  SQL query.
 
Usage : dumpyaml.php [options] -d <database>
        dumpyaml.php [options] -d <database> -t table1,table2
        dumpyaml.php [options] -d <database> -q \"SELECT * FROM `mytable`\" -qn custom_name
 
  -h <host>       MySQL database host
  -u <user>       MySQL username
  -p <pass>       MySQL password
  -d <database>   Name of the MySQL database to dump
  -t <table(s)>   Comma delimited list of tables to dump from database
  -q \"<query>\"    SQL query to dump
  -qn <query name>  Name of the \"table\" when using the -q option
  -n              Convert table names to class names
 
";
}
 
/**
 * Reads/parses the command-line arguments
 */
function read_args() {
 
  global $argc, $argv, $DBHOST, $DBUSER, $DBPASS, $DBNAME, $TABLES, $DBQUERY, $QUERYNAME, $CONVERT_NAMES;
 
  while(!empty($argv)) {
 
    $arg = array_shift($argv);
    switch($arg) {
      case '-h':
        $DBHOST = array_shift($argv);
        break;
      case '-u':
        $DBUSER = array_shift($argv);
        break;
      case '-p':
        $DBPASS = array_shift($argv);
        break;
      case '-d':
        $DBNAME = array_shift($argv);
        break;
      case '-t':
        $TABLES = explode(",", array_shift($argv));
        break;
      case '-q':
        $DBQUERY = array_shift($argv);
        break;
      case '-qn':
        $QUERYNAME = array_shift($argv);
        break;
      case '-n':
        $CONVERT_NAMES = true;
        break;
    }
  }
 
  // Validate Command-Line Arguments
  $retVal = true;
  if (empty($DBHOST)) {
    echo "-h <host> is required\n";
    $retVal = false;
  }
  if (empty($DBUSER)) {
    echo "-u <user> is required\n";
    $retVal = false;
  }
  if (empty($DBPASS)) {
    echo "-p <pass> is required\n";
    $retVal = false;
  }
  if (empty($DBNAME)) {
    echo "-d <database> is required\n";
    $retVal = false;
  }
  if (!empty($TABLES) && !empty($DBQUERY)) {
    echo "-t <table(s)> and -q \"<query>\" are mutually exclusive options\n";
    $retVal = false;
  }
  if (!empty($DBQUERY) && empty($QUERYNAME)) {
    echo "-qn <query name> is required when using -q \"<query>\"\n";
    $retVal = false;
  }
  return $retVal;
}
 
/**
 * Takes a table name with underscores and converts it to something
 * like a class name (CAML case and remove the underscores).
 */
function convert_name_to_class($string) {
 
  // Return Value
  $retVal = '';
 
  $tokens = explode('_', $string);
  foreach($tokens as $token) {
    $retVal .= strtoupper(substr($token, 0, 1));
    if (strlen($token) > 1) {
      $retVal .= substr($token, 1);
    }
  }
 
  // Return Value
  return $retVal;
}
 
/**
 * Takes a SQL query and dumps YAML
 */
function sql_to_yaml($link, $sql, $table) {
 
  global $CONVERT_NAMES;
 
  // Run the query
  $result = mysql_query($sql, $link);
 
  if ($result) {
 
    // Output the table name
    echo ($CONVERT_NAMES === true) ? convert_name_to_class($table) . ":\n" : "{$table}:\n";
 
    // Loop over the result set
    while ($row = mysql_fetch_assoc($result)) {
 
      // Output the row/collection indicator
      echo "  -\n";
 
      // Loop over the columns output names and values
      foreach ($row as $key => $value) {
 
        // Do have any newlines or line feeds?
        $literalFlag = (strpos($value, "\r") !== FALSE || strpos($value, "\n") !== FALSE) ? "| " : "";
 
        // Output the key/value pair
        echo "    {$key}: {$literalFlag}{$value}\n";
      }
    }
  }
 
  // Free the result resources
  mysql_free_result($result);
}
 
/**
 * Retrieves the database tables from the database and puts them into the $TABLES array
 */
function get_database_tables($link) {
 
  global $TABLES;
 
  // Run the query
  $result = mysql_query('SHOW TABLES', $link);
 
  if ($result) {
 
    while ($row = mysql_fetch_row($result)) {
      $TABLES[] = $row[0];
    }
  }
 
  // Free the result resources
  mysql_free_result($result);
}
 
/**
 * Main program loop
 */
if (read_args()) {
 
  // Open database connection
  $link = mysql_connect($DBHOST, $DBUSER, $DBPASS);
  if (!$link) {
    die("Could not connect to DB [{$DBUSER}:{$DBPASS}@{$DBHOST}] :: " . mysql_error()) . "\n";
  }
 
  // Select the database
  if (mysql_select_db($DBNAME)) {
 
    // Output header
    echo "---\n";
 
    // Query Mode
    if (!empty($DBQUERY)) {
      sql_to_yaml($link, $DBQUERY, $QUERYNAME);
    }
 
    else {
 
      // If the user has not specified tables then query for them
      if (empty($TABLES)) {
        get_database_tables($link);
      }
 
      // Loop over tables and output YAML
      foreach ($TABLES as $tbl) {
        sql_to_yaml($link, "SELECT * FROM {$tbl}", $tbl);
        echo "\n";
      }
    }
 
    // Output footer
    echo "...\n";
  }
  else {
    echo "Could not select database [{$DBNAME}] :: " . mysql_error() . "\n";
  }
 
  // Close Database
  mysql_close($link);
}
else
{
  usage();
}
?>




15Jul2010

I was working with an application platform that I had just downloaded today. I just wanted to check it out and play with it a bit. In the application framework was an executable script that provided some command line utility. I fired up the script and received an error like “PHP Fatal error: require_once(): Failed opening required…”. Of course non of the files from the downloaded archived were in the include path for my system, but I didn’t want to just go adding it to my php.ini file just to play around with it short term. What to do.

Command Line Options

First I wanted to see if there was a command line option that I could pass to PHP to tell it what include_path to use for just this one execution. If you execute the following you’ll see the usage:
php --help
There is no include_path command line option, but there is the -d foo[=bar] option which allows us to modify any of the INI entries by key/value.

A Little Parsing

Now all we need to do is combine the -i option, which lists a bunch of information about PHP including the INI entries, with some parsing and we can get the current include_path value. This command will show us the current value:

php -i | grep include_path
 
include_path => .:/usr/local/lib/php:/usr/local/php5/lib/pear => .:/usr/local/lib/php:/usr/local/php5/lib/pear

Of course we’ll need to get just the value if we want to modify it:

php -i | grep include_path | awk 'BEGIN{ FS=" => " }{ print $NF }'
 
.:/usr/local/lib/php:/usr/local/php5/lib/pear

In the awk script above you’ll see that we set the FS (field separator) system variable to split up the line we get from the php -i | grep include_path call. We also take advantage of the NF (number of fields) system variable to print out the last field, which happens to be the value of include_path.

Putting It All Together

Using this, we can now construct our own value to pass in to the include_path for PHP.

#!/bin/bash
 
INCPATH="`php -i | grep include_path | awk 'BEGIN{ FS=" => " }{ printf($NF) }'`:/my/custom/path"
echo "Using include_path = ${INCPATH}"
php -d include_path=${INCPATH} my_php_script.php
 
exit 0

Note that instead of using the print command in our awk script we use printf instead. This just prevents awk from outputting a newline after it prints our data. Also note the use of back tics so that we can assign the output of an execution to a variable. We then append our own path to that and we have our new include_path.




28Jun2010

I just opened up the Mashable app on my iPhone to view an article and received the error below stating, “You need Adobe Flash Player 8 (or above) to view the charts. It is a free and lightweight installation from Adobe.com. Please click on Ok to install the same.” Hey guys… are you aware of the whole Apple / Flash controversy? I’m guessing your iPhone app shouldn’t be prompting me to install Flash.




22Mar2010

Whenever I’m working with Java code I have a habit of opening up a web browser and going to http://java.sun.com immediately. From there I select the Java API Reference and away I go writing Java code. I did the same thing today and was a bit shocked that the Oracle brand has completely infiltrated the Java site. I knew Oracle had acquired Sun, but it wasn’t until today that I really looked at that reality.

Not that it matters much, but I thought it was interesting.




22Dec2009

WordPress 2.9 was release somewhat recently and so like a good WP minion I logged into my site and clicked the update button. Error… uh oh. Apparently WordPress 2.9 requires a more recent version of MySQL (>= 4.1.2). My host installed MySQL 5 ages ago but I’ve never bothered with migrating to the new version because I didn’t have a reason to. Now I do. So here’s how my upgrade went.

First I made a full backup of both the web content and the MySQL database. The MySQL database backup was just a mysqldump command like so:

mysqldump -h [HOST] \
          -u [USER] \
          -p[PASSWORD] \
          [DATABASE NAME] > franzone_com_backup.sql

I then restored the SQL backup  to my new MySQL 5 database like so:

mysql -h [HOST] \
      -u [USER] \
      -p[PASSWORD] \
      [DATABASE NAME] < franzone_com_backup.sql

Amazingly I did not have any errors… I guess it is a good day! Next I changed my WordPress config to point to the new database by modifying <WEB HOME>/wp-config.php and setting the appropriate new values in:

// Put the appropriate values for your environment
define('DB_NAME', 'DATABASE_NAME');
define('DB_USER', 'USERNAME');
define('DB_PASSWORD', 'PASSWORD');
define('DB_HOST', 'HOST');

I pulled up http://www.franzone.com and all looked fine (other than the fact that my blog design is in serious need of updating). I then logged into my WordPress administration site and flushed the cache from WP-Super-Cache and went back to the home page. Everything still looks fine. Now I updated my backup scripts with the new database information and performed yet another backup.

Ok, final step is to upgrade WordPress. I can login to the WordPress administration and have the software do this for me automagically. Everything went smoothly. One last backup and I’m done.




30Nov2009

xkcd_book_300Some people have said that, “laughter is the best medicine.” Well, today’s geek gift idea is the gift of laughter; the kind that appeals to geeks in particular. xkcd is described as a webcomic of romance, sarcasm, math and language. This book, xkcd: volume 0, is the first book that combines selections of the first 600 comics, including various author and fan favorites.

The cost is US $18.00 and is printed by BreadPig. Another thing that makes this a really neat gift idea is that BreadPig’s portion of the profits will go to build a school in Laos through the charity Room to Read.




27Nov2009

cbfb_2010_custom_despair_calendar

Why not start off the Geek Gift Ideas 2009 edition with a Despair, Inc. 2010 Custom Calendar. Every geek loves geek humor and Despair Inc. has been dishing out the sarcasm for years now. Not only does this calendar provide a hilarious demotivator for each month, but it also contains important dates in geek history. For example:

  • January 9, 2007: Apple CEO Steve Jobs announces the iPhone. Motorola cringes.
  • February 26, 1955: George Smith makes aviation history by becoming the first man to bail out of a jet at supersonic speeds
  • March 18, 1947: Patent #2417786 was issued to Hurley Smith for the “Pocket Shield Or Protector”. The nerd is born.
  • April 28, 1997: Duke Nukem Forever’ announced. 12 years later, it remains unreleased.

The calendar costs US $15.99 and will earn you 225 geek points.




27Nov2009

It has been since March that I posted a Friday Song Of The Day, so I figured I’d kick off this Christmas season with a Christmas tune. John Lennon’s Happy Xmas (War Is Over) seemed apropos to both the season of the year and our country.

Happy Christmas Kyoko
Happy Christmas Julian

So this is Christmas
And what have you done
Another year over
And a new one just begun
And so this is Christmas
I hope you have fun
The near and the dear ones
The old and the young

A very merry Christmas
And a happy New Year
Let’s hope it’s a good one
Without any fear

And so this is Christmas (War is over)
For weak and for strong (If you want it)
For rich and the poor ones (War is over)
The road is so long (Now)
And so Happy Christmas (War is over)
For black and for white (If you want it)
For yellow and red ones (War is over)
Let’s stop all the fight (Now)

A very merry Christmas
And a happy New Year
Let’s hope it’s a good one
Without any fear

So this is Christmas (War is over)
And what have we done (If you want it)
Another year over (War is over)
And a new one just begun (Now)
And so Happy Christmas (War is over)
We hope you have fun (If you want it)
The near and the dear one (War is over)
The old and the young (Now)

A very merry Christmas
And a happy New Year
Let’s hope it’s a good one
Without any fear

War is over if you want it
War is over now

Here is a YouTube video with the music and some pictures.

* Click through to the site if you cannot see the video above.




26Nov2009

This is a hilarious video about what the world will view as The Beatles in another thousand years. I really enjoyed the musical reconstruction midway complete with a theremin.

Oh, and by the way… Happy Thanksgiving!