i have some config files (exports from firewall reports in fact) using that kind of structure :
 policies {
        apply-groups default-log;
        from-zone Trust to-zone DMZ {
            policy policy-66 {
                match {
                    source-address g_DMZ_SRV_;
                    destination-address g_DMZ_SRV;
                    application any;
                }
                then {
                    permit;
                }
            }
            policy policy-9 {
                match {
                    source-address g_h_OpenMail-Server;
                    destination-address g_in_DMZ_Exchange;
                    application t_1023;
                }
                then {
                    permit;
                }
            }
        }
        from-zone DMZ to-zone Blabla {
            policy policy-68 {
                match {
                    source-address g_DMZ_SRV_2_;
                    destination-address g_DMZ_SRV_3;
                    application T_22-ssh;
                }
                then {
                    permit;
                }
            }
            policy policy-95 {
                match {
                    source-address g_h_OpenMail-Server-2;
                    source-address 1.2.0.3;
                    destination-address g_in_DMZ_Exchange-1;
                    destination-address 10.25.32.64;
                    application t_1024;
                }
                then {
                    permit;
                }
            }
        }
}
and I would like to parse it in Perl, in order to build a hash for example (or simply put conditions to treat the data) that I could exploit afterwards, e.g something like:
Trust-to-DMZ
      policy-66
            source => g_DMZ_SRV
            destination => blabla
      policy-44
            source => source1
                      source2
                      source3
            destination => dest1
            ports => port1
DMZ-to-Trust
      policy-XX
i wanted wanted to know :
- if you knew some modules helpîng in such a task (i suppose i could use Text::Balanced, i found some examples in a few other posts) 
- if there was some methods/best practices in doing this to avoid dirty work ? 
i suppose i could "count" the number of braces and do loops in loops.. but it would be dirty.
isn't there an easier solution or module doing this automatically ? (like modules exist for XML files for example, XML::Simple putting the contents of an XML into a hash, i would expect something similar for that kind of stuff ?)
otherwise i'll start coding something dirty and post my progress here
thanks!
edit on June 8th, just so you know, it works with a dirty dirty dirty code like that (I'm not a developer, apologies), which is not really what I want as it's not adaptable.. and clearly dirty as hell you have been warned! :) so don't look at it if you don't want blood in your eyes
use warnings;
use lib '/opt/csm/64-bit/cpan/5.16.3-2013.03/lib';
use Data::Dumper;
my ( $policies_flag, $fromzone_flag, $policy_flag, $match_flag, $zone_flag ) = ( 0,0,0,0,0 );
my ( $details_flag, $clos_flag, $then_flag, $permit_flag, $clos2_flag, $final_flag ) = ( 0,0,0,0,0,0 );
my $fromzone;
my $tozone;
my %pols;
my $clos_counter;
die "Usage: $0 <path_to_file>" if $ARGV[0] eq '';
open D, '<', $ARGV[0] or die "cannot open $ARGV[0] for read\n";
@data = <D>;
close D;
OUTER: foreach my $str (@data) {
     next if $str =~ /^$/;
     next if $str =~ /apply-groups/;
     chomp $str;
if ( $str =~ /\s*policies\s+\{/ ) {
        $policies_flag = 1;
        next OUTER;
}
# policies
if ($policies_flag == 1) {
    if ($str =~ /from-zone\s\S+\sto-zone\s\S+\s\{$/) {
        next if $str =~ /(<|>)/;
        ( $fromzone, $tozone ) = ( split(/\s+/,$str) )[2,4];
        $fromzone_flag = 1;
        next OUTER;
    }
    # from-zone
    if ($fromzone_flag == 1) {
        if ($str =~ /policy\s+\S+\s+\{/) {
            $policy_flag = 1;
            $clos_counter=0;
            ( $policy_name ) = ( split(/\s+/, $str) )[2];
            $pols{$policy_name}{from_zone} = "$fromzone";
            $pols{$policy_name}{to_zone} = "$tozone";
            next OUTER;
        }
        # pol
        if ($policy_flag == 1) {
            if ($str =~ /match\s+\{/) {
                $match_flag = 1;
                next OUTER;
            }
        }
        # match
        if ($match_flag == 1) {
            if ($str =~ /\S+\s+\S+;$/) {
                $details_flag = 1;
                if ($str =~ /source-address/) {
                    ( $sources ) = ( split(/\s+/, $str) )[2];
                    $sources =~ s/;//;
                    push( @{$pols{$policy_name}{sources}}, "$sources");
                } elsif ($str =~ /destination-address/) {
                    ( $dests ) = ( split(/\s+/, $str) )[2];
                    $dests =~ s/;//;
                    push( @{$pols{$policy_name}{destinations}}, "$dests");
                } elsif ($str =~ /application/) {
                    ( $ports ) = ( split(/\s+/, $str) )[2];
                    $ports =~ s/;//;
                    push( @{$pols{$policy_name}{ports}}, "$ports");
                }
                next OUTER;
            }
        }
        # rest
        if ($details_flag == 1) {
            if ($str =~ /\s*\}\s*$/) {
                if ($clos_counter == 0) {
                    $clos_flag = 1;
                    $clos_counter++;
                    next OUTER;
                }
            }
        }
        # then
        if ($clos_flag == 1) {
            if ($str =~ /\s*then\s+\{$/) {
                $then_flag = 1;
                next OUTER;
            }
        }
        # permit
        if ($then_flag == 1) {
            if ($str =~ /\s*permit;$/) {
                $permit_flag = 1;
                $pols{$policy_name}{action} = ( split(/\s+/,$str) )[1];
                next OUTER;
            }
        }
        # clos2
        if ($permit_flag == 1) {
            if ($str =~ /\s*\}\s*$/) {
                if ($clos_counter == 1) {
                    $clos2_flag = 1;
                    $clos_counter++;
                    next OUTER;
                }
            }
        }
        # final close
        if ($clos2_flag == 1) {
            if ($str =~ /\s*\}\s*$/) {
                if ($clos_counter == 2) {
                    $final_flag = 1;
                    $clos_counter++;
                    next OUTER;
                }
            }
        }
        # ultimate zone
        if ($final_flag == 1) {
            if ($str =~ /\s*\}\s*$/) {
                if ($clos_counter == 3) {
                    $zone_flag = 1;
                    $clos_counter++;
                    next OUTER;
                }
            }
        }
        # ulti pols
        if ($zone_flag == 1) {
            if ($str =~ /\s*\}\s*$/) {
                if ($clos_counter == 4) {
                    $clos_counter++;
                    last OUTER;
                }
            }
        }
    }
}
}
print Dumper(\%pols);
which gives:
$VAR1 = {
      'policy-68' => {
                       'ports' => [
                                    'T_22-ssh'
                                  ],
                       'sources' => [
                                      'g_DMZ_SRV_2_'
                                    ],
                       'to_zone' => 'Blabla',
                       'from_zone' => 'DMZ',
                       'action' => 'permit;',
                       'destinations' => [
                                           'g_DMZ_SRV_3'
                                         ]
                     },
      'policy-9' => {
                      'ports' => [
                                   't_1023'
                                 ],
                      'sources' => [
                                     'g_h_OpenMail-Server'
                                   ],
                      'to_zone' => 'DMZ',
                      'from_zone' => 'Trust',
                      'action' => 'permit;',
                      'destinations' => [
                                          'g_in_DMZ_Exchange'
                                        ]
                    },
      'policy-66' => {
                       'ports' => [
                                    'any'
                                  ],
                       'sources' => [
                                      'g_DMZ_SRV_'
                                    ],
                       'to_zone' => 'DMZ',
                       'from_zone' => 'Trust',
                       'action' => 'permit;',
                       'destinations' => [
                                           'g_DMZ_SRV'
                                         ]
                     },
      'policy-95' => {
                       'ports' => [
                                    't_1024'
                                  ],
                       'sources' => [
                                      'g_h_OpenMail-Server-2',
                                      '1.2.0.3'
                                    ],
                       'to_zone' => 'Blabla',
                       'from_zone' => 'DMZ',
                       'action' => 'permit;',
                       'destinations' => [
                                           'g_in_DMZ_Exchange-1',
                                           '10.25.32.64'
                                         ]
                     }
    };
 
    