#!perl
# http://www.nicholson.com/rhn/pilot/pdb.txt  says:
#      #define dmDBNameLength    32/* 31 chars + 1 null terminator */
# 
#      struct pdb_header {       /* 78 bytes total */
# 	    char   name[ dmDBNameLength ];
# 	    DWord  attributes;
# 	    Word   version;
# 	    DWord  create_time;
# 	    DWord  modify_time;
# 	    DWord  backup_time;
# 	    DWord  modificationNumber;
# 	    DWord  appInfoID;
# 	    DWord  sortInfoID;
# 	    char   type[4];
# 	    char   creator[4];
# 	    DWord  id_seed;
# 	    DWord  nextRecordList;
# 	    Word   numRecords;
#      };
# 
#      struct pdb_rec_header {   /* 8 bytes total */
# 	    DWord  offset;
# 	    struct {
# 		   int delete    : 1;
# 		   int dirty     : 1;
# 		   int busy      : 1;
# 		   int secret    : 1;
# 		   int category  : 4;
# 	    }      attributes;
# 	    char   uniqueID[3];
#      }

$pdb_header = "a32 n n N N N N N N a4 a4 N N n";
$pdb_rec_header = "N C a3";

$sz_pdb_header = length(pack($pdb_header, "\0" x 1024));
$sz_pdb_rec_header = length(pack($pdb_rec_header, "\0" x 1024));

if ($debug) {
print "sz_pdb_header: $sz_pdb_header\n";
print "sz_pdb_rec_header: $sz_pdb_rec_header\n";
}
$fn = shift;
$output_type = shift;
$output_type = "raw" if not defined $output_type;
{
    open(PDB,"<$fn");
    local $/;
    $/ = undef;
    $pdbh = <PDB>;
    close(PDB);
}

($name,
 $attributes,
 $version,
 $create_time,
 $modify_time,
 $backup_time,
 $modificationNumber,
 $appInfoID,
 $sortInfoID,
 $type,
 $creator,
 $id_seed,
 $nextRecordList,
 $numRecords) = unpack $pdb_header,$pdbh;
 
if ($debug) {
print "name: $name\n";
print "attributes: $attributes\n";
print "version: $version\n";
print "create_time: $create_time\n";
print "modify_time: $modify_time\n";
print "backup_time: $backup_time\n";
print "modificationNumber: $modificationNumber\n";
print "appInfoID: $appInfoID\n";
print "sortInfoID: $sortInfoID\n";
print "type: $type\n";
print "creator: $creator\n";
print "id_seed: $id_seed\n";
print "nextRecordList: $nextRecordList\n";
print "numRecords: $numRecords\n";
}

%tagmap = ( 1 => "Spent", 2 => "Change", 3 => "ATM", 9 => "bugcheck" );

# use appInfoID
if ($appInfoID) {
    ($dbver, $app_balance) = unpack "x".($appInfoID)."n N", $pdbh;
    if ($dbver != 1) {
	print STDERR "Warning, dbver $dbver\n";
	if ($dbver == 0) {
	    # WalletInfo_00 
	    ($app_balance) = unpack "x".($appInfoID)."N", $pdbh;
	}
    }
    $app_balance = unpack("l",pack("L",$app_balance));
}

if ($output_type eq "xml") {
    print "<wallet balance=$app_balance>\n";
} elsif ($output_type eq "html") {
    print "<table>\n";
    print "<th><td colspan=3>Balance $app_balance</td></th>\n" if $appInfoID;
    print "<th><td>Tag</td><td>Unix Time</td><td>Amount</td></th>\n";
} else {
    print "Balance, 0, $app_balance\n";
}

for $i (0..$numRecords-1) {
    ($rh_offset[$i], $rh_attributes[$i], $rh_uniqueID[$i]) =
	unpack "x".($sz_pdb_header + $i * $sz_pdb_rec_header).$pdb_rec_header,
	$pdbh;

if ($debug) {
    print "rh_offset[$i]: $rh_offset[$i]\n";
    print "rh_attributes[$i]: $rh_attributes[$i]\n";
    print "rh_uniqueID[$i]: $rh_uniqueID[$i]\n";
}
    ($wallet_tn[$i], $wallet_tstamp[$i], $wallet_cents[$i]) =
	unpack "x".$rh_offset[$i]."C N N", $pdbh;

    $wallet_tag[$i]   = $tagmap{$wallet_tn[$i]};
    $wallet_cents[$i] = unpack("l",pack("L",$wallet_cents[$i]));

if ($debug) {
    print "wallet_tn[$i]: $wallet_tn[$i]\n";
    print "wallet_tag[$i]: $wallet_tag[$i]\n";
    print "wallet_tstamp[$i]: $wallet_tstamp[$i]\n";
    print "wallet_cents[$i]: $wallet_cents[$i]\n";
}
    # (- 1970 1904)(/ 66.0 4)16.5
    # (+ (* 365 66) 16)24106
    # (* 86400.0 24106)2082758400.0
    $wallet_unix_ts[$i] = $wallet_tstamp[$i] - 2082758400;

    if ($output_type eq "xml") {
	print "<walletrec>\n";
	print "<tag>$wallet_tag[$i]</tag>\n";
	print "<time>$wallet_unix_ts[$i]</time>\n";
	print "<cents>$wallet_cents[$i]</cents>\n";
	print "</walletrec>\n";
    } elsif ($output_type eq "html") {
	print "<tr>\n";
	print "<td>$wallet_tag[$i]</td>\n";
	print "<td>$wallet_unix_ts[$i]</td>\n";
	print "<td>$wallet_cents[$i]</td>\n";
	print "</tr>\n";
    } elsif ($output_type eq "raw") {
	print qq{$wallet_tag[$i], $wallet_unix_ts[$i], $wallet_cents[$i]\n};
    }
}

if ($output_type eq "xml") {
    print "</wallet>\n";
} elsif ($output_type eq "html") {
    print "</table>\n";
}
