Skip Menu |

This queue is for tickets about the AMF-Perl CPAN distribution.

Report information
The Basics
Id: 16174
Status: new
Priority: 0/
Queue: AMF-Perl

People
Owner: Nobody in particular
Requestors: chris+rt [...] chrisdolan.net
Cc:
AdminCc:

Bug Information
Severity: Normal
Broken in: 0.15
Fixed in: (no value)



Subject: readData type == 8
The implementation for readData($type == 8) in the Deserializer should parse a hash. Cribbing from the Ruby implementation at http://www.inlet-media.de/flvtool2/ and from the readArray method, I figured out how to do that. The attached patch implements a new readHash method which I've successfully tested against some embedded FLV 1.1 AMF data. I have not done the corresponding Serializer.pm method, but it should be easy. -- Chris
diff -ur AMF-Perl-0.15-orig/lib/AMF/Perl/IO/Deserializer.pm AMF-Perl-0.15/lib/AMF/Perl/IO/Deserializer.pm --- AMF-Perl-0.15-orig/lib/AMF/Perl/IO/Deserializer.pm 2004-09-19 12:08:47.000000000 -0500 +++ AMF-Perl-0.15/lib/AMF/Perl/IO/Deserializer.pm 2005-11-28 23:50:33.000000000 -0600 @@ -182,6 +182,29 @@ return \@ret; } +# reads a hash object and converts the binary data into a Perl array +sub readHash +{ + my ($self)=@_; + # init the hash + print "readHash\n"; + my %ret; + # get the length of the array + my $length = $self->{inputStream}->readLong(); + die "Malformed AMF data, array length too big" if $length > $self->{inputStream}{content_length}; + # loop over all of the elements in the data + for (my $i=0; $i<$length; $i++) + { + my $key = $self->readString(); + # grab the type for each element + my $type = $self->{inputStream}->readByte(); + # grab each element + $ret{$key} = $self->readData($type); + } + # return the data + return \%ret; +} + sub readCustomClass { my ($self)=@_; @@ -308,15 +331,9 @@ { $data = $self->readFlushedSO(); } - elsif ($type == 8) # array + elsif ($type == 8) # mixed array { - # shared object format only (*.sol) - # only time I saw it was the serverinfo value in a ColdFusion RecordSet - # It was just four zeroes - skip them. - for (my $i=0; $i<4; $i++) - { - $self->{inputStream}->readByte(); - } + $data = $self->readHash(); } elsif ($type == 10) # array {
From: cdolan [...] cpan.org
[CLOTHO - Tue Nov 29 00:57:00 2005]: Show quoted text
> The implementation for readData($type == 8) in the Deserializer should > parse a hash. Cribbing from the Ruby implementation at > http://www.inlet-media.de/flvtool2/ and from the readArray method, > I figured out how to do that. The attached patch implements a new > readHash method which I've successfully tested against some > embedded FLV 1.1 AMF data. I have not done the corresponding > Serializer.pm method, but it should be easy. > > -- Chris
Oops, here's another attempt at the patch. Strangely, it looks like the size property of the hash is unused. Instead, the hash is terminated by a zero-length string as the hash key. This implementation loops until that empty string is found, unlike the previous version which looped a fixed number of times. I don't know enough about AMF to say whether the FLV data I'm looking at is flaky AMF, or if it's supposed to be like that. I suspect the latter, because the FLV file was created by On2's FLV exporter, so it's fairly official I'd guess. -- Chris
diff -ur AMF-Perl-0.15-orig/lib/AMF/Perl/IO/Deserializer.pm AMF-Perl-0.15/lib/AMF/Perl/IO/Deserializer.pm --- AMF-Perl-0.15-orig/lib/AMF/Perl/IO/Deserializer.pm 2004-09-19 12:08:47.000000000 -0500 +++ AMF-Perl-0.15/lib/AMF/Perl/IO/Deserializer.pm 2005-11-29 00:11:31.000000000 -0600 @@ -182,6 +182,37 @@ return \@ret; } +# reads a hash object and converts the binary data into a Perl array +sub readHash +{ + my ($self)=@_; + # init the hash + my %ret; + # get the length of the array + # This length is actually unused! + my $length = $self->{inputStream}->readLong(); + #die "Malformed AMF data, array length too big" if $length > $self->{inputStream}{content_length}; + # loop over all of the elements in the data + while (1) + { + my $key = ''; + eval + { + $key = $self->readString(); + if ($key ne '') + { + # grab the type for each element + my $type = $self->{inputStream}->readByte(); + # grab each element + $ret{$key} = $self->readData($type); + } + }; + last if $key eq ''; + } + # return the data + return \%ret; +} + sub readCustomClass { my ($self)=@_; @@ -308,15 +339,9 @@ { $data = $self->readFlushedSO(); } - elsif ($type == 8) # array + elsif ($type == 8) # mixed array { - # shared object format only (*.sol) - # only time I saw it was the serverinfo value in a ColdFusion RecordSet - # It was just four zeroes - skip them. - for (my $i=0; $i<4; $i++) - { - $self->{inputStream}->readByte(); - } + $data = $self->readHash(); } elsif ($type == 10) # array {