diff --git a/CHANGES.txt b/CHANGES.txt
index a7cec73197d2e3efc18ea197d9c00f43f285a4e8..894289fed49db464d43d6c791df2e3c580cbb12e 100644
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -40,6 +40,9 @@ instead of fs_dir_add().
 2/6/09: Bug Fix: Fixed bug 2568528, which was caused by incorrect 
 adjustment of attribute FILLER offset.  Reported by Andy Bontoft.
 
+2/13/09: Bug Fix: Fixed bug 2596397, which was caused by mactime
+doing text-based sorting on dates of different lengths (fix was to
+pad with 0s).  Fix by Bruce Nikkel.
 
 
 ---------------- VERSION 3.0.0 -------------- 
diff --git a/tools/timeline/mactime.base b/tools/timeline/mactime.base
index 7f272b00998c5ce0902f7adec8b1e2fadc1b7fbc..0a7d03462bbcc545adc0346abf4b35f3b142cf8d 100644
--- a/tools/timeline/mactime.base
+++ b/tools/timeline/mactime.base
@@ -9,13 +9,13 @@
 #
 # The Sleuth Kit
 # Brian Carrier [carrier <at> sleuthkit [dot] org]
-# Copyright (c) 2003-2008 Brian Carrier.  All rights reserved
+# Copyright (c) 2003-2009 Brian Carrier.  All rights reserved
 #
 # TASK
 # Copyright (c) 2002 Brian Carrier, @stake Inc.  All rights reserved
 #
 #
-# The modifications to the original mactime are distributed under 
+# The modifications to the original mactime are distributed under
 # the Common Public License 1.0
 #
 #
@@ -93,13 +93,13 @@ sub version {
 my $month_num  = 0;
 my $header     = 0;
 
-my $in_seconds = 0;
+my $in_seconds  = 0;
 my $out_seconds = 0;
-my %time2macstr;
+my %timestr2macstr;
 my %file2other;
 
-my %gid2names    = ();
-my %uid2names    = ();
+my %gid2names = ();
+my %uid2names = ();
 
 usage() if (scalar(@ARGV) == 0);
 
@@ -226,7 +226,7 @@ sub version {
     }
 }
 else {
-    $in_seconds = 0;
+    $in_seconds  = 0;
     $out_seconds = 0;
 }
 
@@ -260,14 +260,15 @@ sub version {
 sub parse_isodate {
     my $iso_date = shift;
 
-    my $sec  =  0;
-    my $min  =  0;
-    my $hour =  0;
+    my $sec  = 0;
+    my $min  = 0;
+    my $hour = 0;
     my $wday = 0;
     my $yday = 0;
     if ($iso_date =~ /^(\d\d\d\d)\-(\d\d)\-(\d\d)$/) {
-        return mktime ($sec, $min, $hour, $3, $2 - 1, $1 - 1900, $wday, $yday);
-    } else {
+        return mktime($sec, $min, $hour, $3, $2 - 1, $1 - 1900, $wday, $yday);
+    }
+    else {
         return -1;
     }
 }
@@ -287,20 +288,20 @@ sub read_body {
         chomp;
 
         my (
-            $tmp1,      $file,     $st_ino, $st_ls,
-            $st_uid,   $st_gid,   $st_size, $st_atime,
+            $tmp1,     $file,     $st_ino,    $st_ls,
+            $st_uid,   $st_gid,   $st_size,   $st_atime,
             $st_mtime, $st_ctime, $st_crtime, $tmp2
           )
           = &tm_split($_);
 
         # Sanity check so that we ignore the header entries
-        next unless ((defined $st_ino)   && ($st_ino   =~ /[\d-]+/));
-        next unless ((defined $st_uid) && ($st_uid =~ /\d+/));
-        next unless ((defined $st_gid) && ($st_gid =~ /\d+/));
-        next unless ((defined $st_size) && ($st_gid =~ /\d+/));
-        next unless ((defined $st_mtime) && ($st_mtime =~ /\d+/));
-        next unless ((defined $st_atime) && ($st_atime =~ /\d+/));
-        next unless ((defined $st_ctime) && ($st_ctime =~ /\d+/));
+        next unless ((defined $st_ino)    && ($st_ino    =~ /[\d-]+/));
+        next unless ((defined $st_uid)    && ($st_uid    =~ /\d+/));
+        next unless ((defined $st_gid)    && ($st_gid    =~ /\d+/));
+        next unless ((defined $st_size)   && ($st_gid    =~ /\d+/));
+        next unless ((defined $st_mtime)  && ($st_mtime  =~ /\d+/));
+        next unless ((defined $st_atime)  && ($st_atime  =~ /\d+/));
+        next unless ((defined $st_ctime)  && ($st_ctime  =~ /\d+/));
         next unless ((defined $st_crtime) && ($st_crtime =~ /\d+/));
 
         # we need *some* value in mactimes!
@@ -313,71 +314,79 @@ sub read_body {
             && ($st_ctime < $in_seconds)
             && ($st_crtime < $in_seconds));
 
-        #  First, put all the times in one big array...
+        # add leading zeros to timestamps because we will later sort
+        # these using a string-based comparison
+        $st_mtime  = sprintf("%.10d", $st_mtime);
+        $st_atime  = sprintf("%.10d", $st_atime);
+        $st_ctime  = sprintf("%.10d", $st_ctime);
+        $st_crtime = sprintf("%.10d", $st_crtime);
+
+        # Put all the times in one big array along with the inode and
+        # name (they are used in the final sorting)
 
         # If the date on the file is too old, don't put it in the array
         my $post = ",$st_ino,$file";
 
         if ($out_seconds) {
-            $time2macstr{"$st_mtime$post"} .= "m"
+            $timestr2macstr{"$st_mtime$post"} .= "m"
               if (
                    ($st_mtime >= $in_seconds)
                 && ($st_mtime < $out_seconds)
-                && (   (!(exists $time2macstr{"$st_mtime$post"}))
-                    || ($time2macstr{"$st_mtime$post"} !~ /m/))
+                && (   (!(exists $timestr2macstr{"$st_mtime$post"}))
+                    || ($timestr2macstr{"$st_mtime$post"} !~ /m/))
               );
 
-            $time2macstr{"$st_atime$post"} .= "a"
+            $timestr2macstr{"$st_atime$post"} .= "a"
               if (
                    ($st_atime >= $in_seconds)
                 && ($st_atime < $out_seconds)
-                && (   (!(exists $time2macstr{"$st_atime$post"}))
-                    || ($time2macstr{"$st_atime$post"} !~ /a/))
+                && (   (!(exists $timestr2macstr{"$st_atime$post"}))
+                    || ($timestr2macstr{"$st_atime$post"} !~ /a/))
               );
 
-            $time2macstr{"$st_ctime$post"} .= "c"
+            $timestr2macstr{"$st_ctime$post"} .= "c"
               if (
                    ($st_ctime >= $in_seconds)
                 && ($st_ctime < $out_seconds)
-                && (   (!(exists $time2macstr{"$st_ctime$post"}))
-                    || ($time2macstr{"$st_ctime$post"} !~ /c/))
+                && (   (!(exists $timestr2macstr{"$st_ctime$post"}))
+                    || ($timestr2macstr{"$st_ctime$post"} !~ /c/))
               );
 
-            $time2macstr{"$st_crtime$post"} .= "b"
+            $timestr2macstr{"$st_crtime$post"} .= "b"
               if (
                    ($st_crtime >= $in_seconds)
                 && ($st_crtime < $out_seconds)
-                && (   (!(exists $time2macstr{"$st_crtime$post"}))
-                    || ($time2macstr{"$st_crtime$post"} !~ /b/))
+                && (   (!(exists $timestr2macstr{"$st_crtime$post"}))
+                    || ($timestr2macstr{"$st_crtime$post"} !~ /b/))
               );
         }
         else {
-            $time2macstr{"$st_mtime$post"} .= "m"
+            $timestr2macstr{"$st_mtime$post"} .= "m"
               if (
                 ($st_mtime >= $in_seconds)
-                && (   (!(exists $time2macstr{"$st_mtime$post"}))
-                    || ($time2macstr{"$st_mtime$post"} !~ /m/))
+                && (   (!(exists $timestr2macstr{"$st_mtime$post"}))
+                    || ($timestr2macstr{"$st_mtime$post"} !~ /m/))
               );
 
-            $time2macstr{"$st_atime$post"} .= "a"
+            $timestr2macstr{"$st_atime$post"} .= "a"
               if (
                 ($st_atime >= $in_seconds)
-                && (   (!(exists $time2macstr{"$st_atime$post"}))
-                    || ($time2macstr{"$st_atime$post"} !~ /a/))
+                && (   (!(exists $timestr2macstr{"$st_atime$post"}))
+                    || ($timestr2macstr{"$st_atime$post"} !~ /a/))
               );
 
-            $time2macstr{"$st_ctime$post"} .= "c"
+            $timestr2macstr{"$st_ctime$post"} .= "c"
               if (
                 ($st_ctime >= $in_seconds)
-                && (   (!(exists $time2macstr{"$st_ctime$post"}))
-                    || ($time2macstr{"$st_ctime$post"} !~ /c/))
+                && (   (!(exists $timestr2macstr{"$st_ctime$post"}))
+                    || ($timestr2macstr{"$st_ctime$post"} !~ /c/))
               );
 
-            $time2macstr{"$st_crtime$post"} .= "b"
+            $timestr2macstr{"$st_crtime$post"} .= "b"
               if (
                 ($st_crtime >= $in_seconds)
-                && (   (!(exists $time2macstr{"$st_crtime$post"}))
-                    || ($time2macstr{"$st_crtime$post"} !~ /b/))
+                && (   (!(exists $timestr2macstr{"$st_crtime$post"}))
+                    || ($timestr2macstr{"$st_crtime$post"} !~ /b/))
               );
         }
 
@@ -438,9 +447,9 @@ sub print_header {
 #
 sub print_tl {
 
-    my $prev_day  = "";    # has the format of 'day day_week mon year'
-    my $prev_hour = "";    # has just the hour and is used for hourly index
-    my $prev_cnt  = 0;
+    my $prev_day        = "";   # has the format of 'day day_week mon year'
+    my $prev_hour       = "";   # has just the hour and is used for hourly index
+    my $prev_cnt        = 0;
     my $old_date_string = "";
 
     my $delim = ":";
@@ -449,7 +458,10 @@ sub print_tl {
         $delim = ",";
     }
 
-    for my $key (sort { $a cmp $b } keys %time2macstr) {
+    # Cycle through the files and print them in sorted order.
+    # Note that we sort using a string comparison because the keys
+    # also contain the inode and file name
+    for my $key (sort { $a cmp $b } keys %timestr2macstr) {
         my $time;
         my $inode;
         my $file;
@@ -588,32 +600,36 @@ sub print_tl {
         #
         #  Muck around with the [mac]times string to make it pretty.
         #
-        my $mactime_tmp = $time2macstr{$key};
-        my $mactime = "";
+        my $mactime_tmp = $timestr2macstr{$key};
+        my $mactime     = "";
         if ($mactime_tmp =~ /m/) {
             $mactime = "m";
-        } else {
+        }
+        else {
             $mactime = ".";
         }
 
         if ($mactime_tmp =~ /a/) {
             $mactime .= "a";
-        } else {
+        }
+        else {
             $mactime .= ".";
         }
 
         if ($mactime_tmp =~ /c/) {
             $mactime .= "c";
-        } else {
+        }
+        else {
             $mactime .= ".";
         }
 
         if ($mactime_tmp =~ /b/) {
             $mactime .= "b";
-        } else {
+        }
+        else {
             $mactime .= ".";
         }
-        
+
         my ($ls, $uids, $groups, $size) = split(/:/, $file2other{$file});
 
         print "FILE: $file MODES: $ls U: $uids G: $groups S: $size\n"
@@ -735,7 +751,6 @@ package main;
 my $passwd_loaded = 0;    # flags to use to avoid reloading everything
 my $group_loaded  = 0;    # unnecessarily...
 
-
 #
 # Update user information for the user named $name.  We cache the password,
 # uid, login group, home directory and shell.
@@ -778,7 +793,6 @@ sub add_gr_info {
     }
 }
 
-
 sub load_passwd_info {
     my ($file_name) = @_;
     my (@pw_info);
@@ -802,7 +816,6 @@ sub load_passwd_info {
     close(FILE);
 }
 
-
 sub load_group_info {
     my ($file_name) = @_;
     my (@gr_info);
@@ -825,7 +838,6 @@ sub load_group_info {
     close(FILE);
 }
 
-
 #
 # Split a time machine record.
 #