sl@0: # sl@0: # Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). sl@0: # All rights reserved. sl@0: # This component and the accompanying materials are made available sl@0: # under the terms of the License "Eclipse Public License v1.0" sl@0: # which accompanies this distribution, and is available sl@0: # at the URL "http://www.eclipse.org/legal/epl-v10.html". sl@0: # sl@0: # Initial Contributors: sl@0: # Nokia Corporation - initial contribution. sl@0: # sl@0: # Contributors: sl@0: # sl@0: # Description: sl@0: # sl@0: #!/bin/perl sl@0: sl@0: use strict; sl@0: use Getopt::Long; sl@0: sl@0: my $DEBUG = 0; sl@0: my $TABS = ""; sl@0: my $OUTPUT_BUFFER = ""; sl@0: sl@0: main(); sl@0: exit; sl@0: sl@0: sub main() { sl@0: my $out; sl@0: my $outFh; sl@0: my $in; sl@0: my @lines; sl@0: sl@0: GetOptions('debug=i' => \$DEBUG, sl@0: 'in=s' => \$in, sl@0: 'out=s' => \$out); sl@0: sl@0: if (! defined $in && defined $ARGV[0]) { sl@0: $in = $ARGV[0]; sl@0: } sl@0: sl@0: if (defined $in) { sl@0: @lines = decompile($in); sl@0: } sl@0: else { sl@0: die "No input file specified.\n"; sl@0: } sl@0: sl@0: if (! defined $out && defined $ARGV[1]) { sl@0: $out = $ARGV[1]; sl@0: } sl@0: if (defined $out) { sl@0: open $outFh, ">$out" || die "Cannot open output file $out"; sl@0: } sl@0: else { sl@0: $outFh = *STDOUT; sl@0: } sl@0: translate(\@lines); sl@0: print $outFh $OUTPUT_BUFFER; sl@0: } sl@0: sl@0: sub translate($) { sl@0: my ($lines) = @_; sl@0: my $lineCount = scalar(@$lines); sl@0: sl@0: for (my $i = 0; $i < $lineCount; ++$i) { sl@0: $_ = @$lines[$i]; sl@0: s/^\s*//g; sl@0: s/\n//g; sl@0: sl@0: if ($DEBUG >= 3) { sl@0: print "$_\n"; sl@0: } sl@0: sl@0: if ( /^OBJECT\s+IDENTIFIER\s*$/ ) { sl@0: if ($DEBUG >= 3) { sl@0: print "reading OID value from next line\n"; sl@0: } sl@0: if (defined @$lines[$i+1]) { sl@0: $_ .= @$lines[++$i]; sl@0: } sl@0: } sl@0: sl@0: if ( /BIT\s+STRING,\s+encapsulates/i ) { sl@0: addToOutput("BITSTRING_WRAPPER"); sl@0: nest(); sl@0: } sl@0: elsif ( /^\s*BIT\s+STRING/i ) { sl@0: # bitstring defined in binary sl@0: if ( $$lines[$i+1] =~ /\'([01]+)\'/ ) { sl@0: $i++; sl@0: addToOutput("BITSTRING=$1"); sl@0: } sl@0: # bit string defined in hex sl@0: elsif ( /^\s*BIT\s+STRING\s+(([A-F0-9][A-F0-9]\s*)+)/i ) { sl@0: my $bitStr = toBitString($1); sl@0: addToOutput("BITSTRING=$bitStr"); sl@0: } sl@0: else { sl@0: # bit string wrapper sl@0: addToOutput("BITSTRING_WRAPPER"); sl@0: nest(); sl@0: addToOutput("RAW \{"); sl@0: nest(); sl@0: $i++; sl@0: addToOutput(getRawHex($lines,\$i)); sl@0: leaveNest(); sl@0: addToOutput(" \}"); sl@0: leaveNest(); sl@0: addToOutput("END"); sl@0: } sl@0: } sl@0: elsif ( /^(BMPSTRING\s+)\'(.*)\'/i ) { sl@0: addToOutput("BMPSTRING=$2"); sl@0: } sl@0: elsif ( /^(BOOLEAN\s+)(.*)/i ) { sl@0: addToOutput("BOOLEAN=$2"); sl@0: } sl@0: elsif ( /(^ENUMERATED\s+)(\d+)*$/i ) { sl@0: # small integer - non hex incoded sl@0: addToOutput("ENUMERATED=$2"); sl@0: } sl@0: elsif ( /^\[(\d+)\]\s*\'(.*)\'/ ) { sl@0: addToOutput("IMPLICIT=$1"); sl@0: nest(); sl@0: addToOutput("PRINTABLESTRING=$2"); sl@0: leaveNest(); sl@0: addToOutput("END"); sl@0: } sl@0: elsif ( /^\[(\d+)\]/ ) { sl@0: # general case for implicit & explicit tags sl@0: my $tag=$1; sl@0: if (defined @$lines[$i+1] && isRawData(@$lines[$i+1])) { sl@0: # if there is only raw data assume implicit sl@0: addToOutput("IMPLICIT=$tag"); sl@0: nest(); sl@0: addToOutput("OCTETSTRING"); sl@0: nest(); sl@0: addToOutput("RAW \{"); sl@0: while (isRawData(@$lines[++$i])) { sl@0: addToOutput("" . @$lines[$i] . ""); sl@0: } sl@0: --$i; sl@0: addToOutput("\}"); sl@0: leaveNest(); sl@0: addToOutput("END"); sl@0: leaveNest(); sl@0: addToOutput("END"); sl@0: leaveNest(); sl@0: } sl@0: else { sl@0: # otherwise assume explicit sl@0: addToOutput("EXPLICIT=$tag"); sl@0: } sl@0: nest(); sl@0: } sl@0: elsif ( /^(IA5STRING\s+)\'(.*)\'/i ) { sl@0: addToOutput("IA5STRING=$2"); sl@0: } sl@0: elsif ( /(^INTEGER\s+)(\d+)*$/i ) { sl@0: # small integer - non hex incoded sl@0: addToOutput("INTEGER=$2"); sl@0: } sl@0: elsif (/^INTEGER/) { sl@0: # big integer sl@0: addToOutput("BIGINTEGER {"); sl@0: my $tmp = $_; sl@0: $tmp =~ s/.*INTEGER\s+//g; sl@0: nest(); sl@0: if (isRawData($tmp)) { sl@0: addToOutput($tmp); sl@0: } sl@0: sl@0: $i++; sl@0: addToOutput(getRawHex($lines,\$i)); sl@0: leaveNest(); sl@0: addToOutput("\}"); sl@0: } sl@0: elsif ( /^NULL/i ) { sl@0: addToOutput("NULL"); sl@0: } sl@0: elsif ( /^OCTET STRING\s*$/i ) { sl@0: $i++; sl@0: addToOutput("OCTETSTRING"); sl@0: nest(); sl@0: addToOutput("RAW \{"); sl@0: nest(); sl@0: addToOutput(getRawHex($lines,\$i)); sl@0: leaveNest(); sl@0: addToOutput("\}"); sl@0: leaveNest(); sl@0: addToOutput("END"); sl@0: } sl@0: elsif ( /^OCTET\s+STRING.*encapsulates/i ) { sl@0: addToOutput("OCTETSTRING"); sl@0: nest(); sl@0: } sl@0: elsif ( /^OCTET\s+STRING/i ) { sl@0: addToOutput("OCTETSTRING"); sl@0: nest(); sl@0: my $hex = $_; sl@0: $hex =~ s/OCTET\s+STRING\s+//g; sl@0: addToOutput("RAW=$hex"); sl@0: leaveNest(); sl@0: addToOutput("END"); sl@0: } sl@0: elsif ( /^OBJECT\s+IDENTIFIER\s+\'([\d ]+)\'/i ) { sl@0: # plain oid sl@0: my $oid = $1; sl@0: $oid =~ s/ /./g; sl@0: addToOutput("OID=$oid"); sl@0: } sl@0: elsif ( /(^OBJECT\s+IDENTIFIER.*\()([\d ]+)/i ) { sl@0: # extra information printed with oid sl@0: my $oid = $2; sl@0: $oid =~ s/ /./g; sl@0: addToOutput("OID=$oid"); sl@0: } sl@0: elsif ( /(^PRINTABLESTRING\s*\')([^\']*)/i ) { sl@0: addToOutput("PRINTABLESTRING=$2"); sl@0: } sl@0: elsif ( /^SEQUENCE/i ) { sl@0: addToOutput("SEQUENCE"); sl@0: nest(); sl@0: } sl@0: elsif ( /^SET/i ) { sl@0: addToOutput("SET"); sl@0: nest(); sl@0: } sl@0: elsif (/^(UTCTIME\s+\')([^\']+)/i) { sl@0: addToOutput("UTCTIME=$2"); sl@0: } sl@0: elsif ( /^(UTF8STRING\s+)\'(.*)\'/i ) { sl@0: addToOutput("UTF8STRING=$2"); sl@0: } sl@0: elsif ( /^\}/) { sl@0: leaveNest(); sl@0: addToOutput("END"); sl@0: } sl@0: elsif (isRawData($_)) { sl@0: my $raw = s/\s+/ /g; sl@0: addToOutput("RAW=$_"); sl@0: } sl@0: sl@0: } sl@0: } sl@0: sl@0: sub addToOutput($) { sl@0: my ($text) = @_; sl@0: sl@0: if ($DEBUG >= 3) { sl@0: print "+${TABS}$text\n"; sl@0: } sl@0: $OUTPUT_BUFFER .= "${TABS}$text\n"; sl@0: } sl@0: sl@0: sub getRawHex($) { sl@0: my ($lines,$index) = @_; sl@0: my $translated = ''; sl@0: sl@0: my $end = 0; sl@0: do { sl@0: my $line = $$lines[$$index]; sl@0: last if (!defined $line); sl@0: chomp($line); sl@0: sl@0: if (isRawData($line)) { sl@0: $line =~ s/^\s+//g; sl@0: addToOutput("$line"); sl@0: $$index++; sl@0: } sl@0: else { sl@0: $$index--; sl@0: $end = 1; sl@0: } sl@0: } while (! $end); sl@0: return $translated; sl@0: } sl@0: sl@0: sub isRawData() { sl@0: my ($line) = @_; sl@0: my $retVal = ($line =~ /^\s*([A-F0-9][A-F0-9]\s?)+$/i); sl@0: if ($DEBUG >= 3 && $retVal) { sl@0: print "RAW: "; sl@0: } sl@0: return $retVal; sl@0: } sl@0: sl@0: sub toBitString() { sl@0: my ($hex) = @_; sl@0: my $bitStr = ""; sl@0: $hex =~ s/\s//g; sl@0: sl@0: for (my $i=0; $i < length($hex); $i+=2) { sl@0: my $num = hex(substr($hex, $i, 2)); sl@0: print ".$num"; sl@0: for (my $j=0; $j < 8; $j++) { sl@0: $bitStr .= ($num & 0x80) ? '1' : '0'; sl@0: $num <<= 1; sl@0: } sl@0: } sl@0: if ($DEBUG >= 2) { sl@0: print "\nbitStr: $hex = $bitStr\n"; sl@0: } sl@0: return $bitStr; sl@0: } sl@0: sl@0: # increment debug tabbing level sl@0: sub nest() { sl@0: $TABS .= " "; sl@0: } sl@0: sl@0: # decrement debug tabbing level sl@0: sub leaveNest() { sl@0: $TABS =~ s/^...//; sl@0: } sl@0: sl@0: sl@0: sub decompile($) { sl@0: my ($inFile) = @_; sl@0: sl@0: sl@0: my @command = ("cmd", sl@0: "/C \"dumpasn1 -apruz $inFile > _dump.tmp\""); sl@0: sl@0: if ((my $err = system(@command)) != 0) { sl@0: die "decode: " . join(" ", @command) . "\nreturned error $err"; sl@0: } sl@0: sl@0: my $dumpFh; sl@0: open $dumpFh, "_dump.tmp"; sl@0: my @lines = <$dumpFh>; sl@0: close $dumpFh; sl@0: sl@0: return @lines; sl@0: }