#!/usr/bin/perl # (c) 2002 Fonkie # License: GPL v2 use Unicode::String qw( utf16 ); use Getopt::Std; use strict; use vars qw( $c %opt ); my $file; my $buff; getopts("d",\%opt); open IN,$ARGV[0]; while (read(IN, $buff, 8 * 2**10)) { $file.=$buff; } close IN; my $attr = { song => { 1 => "title", 2 => "filename", 3 => "album?", 4 => "artist?", 5 => "genre/eq?", 6 => "filetype", 8 => "creator" }, list => { 1 => "songlist", 2 => "playlist" } }; parse_section($file,"MAIN"); exit; sub get_size { my $file=shift; my $hsize=substr($file,4,4); my $size=substr($file,8,4); $hsize=unpack "V",$hsize; $size=unpack "V",$size; $size=$hsize if($size<$hsize); return $size; } sub parse_section { my $file=shift; my $ohead=shift; my @f=(); my $done; while(!$done) { my $size=get_size($file); push @f,substr($file,0,$size); $file=substr($file,$size); $done=1 if(length($file)<=0); $done=1 if($size<=0); } for(@f) { my $file=$_; my $head=substr($file,0,4); my $hsize=substr($file,4,4); my $size=substr($file,8,4); my $len=length($file); next unless($head =~ /^mh/); $hsize=unpack "V",$hsize; $size=unpack "V",$size; $size=$hsize if($size<$hsize); #print "got: $head [$hsize] [$size] [$len]\n"; if($opt{d}) { $c++; my $n=sprintf "%.4d",$c; my $s=$hsize; $s=$size if($head eq "mhod"); open OUT,">dump_$n"; print OUT substr($file,0,$s); close OUT; } # do parsing if($head eq "mhbd") { print "got: main db element [$head] [$hsize] [$size] [$len]\n"; my ($a1,$a2,$a3) = unpack "V4V4V4",substr($file,12,4); print "got: ????: $a1\n"; print "got: ????: $a2\n"; print "got: ????: $a3\n"; } elsif($head eq "mhsd") { print "got: main list element [$head] [$hsize] [$size] [$len]\n"; my ($type) = unpack "V4",substr($file,12,4); my $t=$attr->{list}->{$type}; print "got: type: $t [$type]\n"; } elsif($head eq "mhlt") { print "got: list element [$head] [$hsize] [$size] [$len]\n"; my ($count) = unpack "V4",substr($file,8,4); print "got: songs: $count\n"; } elsif($head eq "mhlp") { print "got: playlist element [$head] [$hsize] [$size] [$len]\n"; my ($count) = unpack "V4",substr($file,8,4); print "got: playlists: $count\n"; } elsif($head eq "mhit") { print "got: song item element [$head] [$hsize] [$size] [$len]\n"; my ($count,$ind,$a3,$a4,$type,$date,$size,$dur,$order, $a10,$a11,$a12,$a13)= unpack "V4V4V4V4V4V4V4V4V4V4V4V4V4",substr($file,12,72); print "got: $count attribute elements\n"; print "got: index: $ind\n"; print "got: ????: $a3\n"; print "got: ????: $a4\n"; print "got: type: $type\n"; my $date_o=$date; $date=$date-2082844800; my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime($date); $year+=1900; $mon+=1; my $d=sprintf "%.4d/%.2d/%.2d %.2d:%.2d:%.2d",$year,$mon,$mday,$hour,$min,$sec; print "got: date: $d [$date_o]\n"; print "got: size: $size\n"; my $h=int(($dur/1000)/60/60); my $m=int(($dur/1000)/60)-60*$h; my $s=int(($dur/1000))-60*$m; my $r=substr($dur,length($dur)-3); my $d=sprintf "%.2d:%.2d:%.2d.%s",$h,$m,$s,$r; print "got: dur: $d [$dur]\n"; print "got: order: $order\n"; print "got: ????: $a10\n"; print "got: ????: $a11\n"; print "got: ????: $a12\n"; print "got: ????: $a13\n"; } elsif($head eq "mhod") { print "got: attribute element [$head] [$hsize] [$size] [$len]\n"; my ($type,$a2,$a3,$a4,$size)= unpack "V4V4V4V4V4",substr($file,12,20); my $t="special"; $t=$attr->{song}->{$type} if($ohead eq "mhit"); print "got: type: $t [$type]\n"; if($type == 100) { print "got: not a string element\n"; print "got: ????: $a2\n"; print "got: ????: $a3\n"; print "got: ????: $a4\n"; print "got: size: $size (?)\n"; } else { print "got: ????: $a4\n"; my $gs=$size-40; $gs=0 if($gs<0); my $s=substr($file,40,$size); my $u=utf16($s); $u->byteswap; my $ustr=$u->latin1; my $l=length $ustr; print "got: size: $l [$size]\n"; print "got: ustr: $ustr\n" if $ustr; } } elsif($head eq "mhyp") { print "got: playlist info [$head] [$hsize] [$size] [$len]\n"; my ($attr,$count,$a3,$a4,$a5,$a6,$a7,$a8,$a9, $a10,$a11,$a12,$a13)= unpack "V4V4V4V4V4V4V4V4V4V4V4V4V4",substr($file,12,72); print "got: attributes: $attr\n"; print "got: songs: $count\n"; print "got: ????: $a3\n"; print "got: ????: $a4\n"; print "got: ????: $a5\n"; print "got: ????: $a6\n"; } elsif($head eq "mhip") { print "got: playlist item element [$head] [$hsize] [$size] [$len]\n"; my ($a1,$a2,$a3,$ref,$a5,$a6,$a7,$a8,$a9, $a10,$a11,$a12,$a13)= unpack "V4V4V4V4V4V4V4V4V4V4V4V4V4",substr($file,12,72); print "got: ????: $a1\n"; print "got: ????: $a2\n"; print "got: ????: $a3\n"; print "got: reference: $ref\n"; print "got: ????: $a5\n"; } else { print "error: unknown header: $head\n"; } print "\n"; # recursion my $f=substr($file,$hsize,$size-$hsize); parse_section($f,$head); } }