This is far from complete, but as the output at the bottom shows, the basic logic is inplace and functional. The regexen will require scrutiny as will the treatment of missing required values and other error handling.

I've written a simplistic parser for the purposes of testing. You my want to reject this in favour of something better.

Hope it at least demonstrates an approach to the problem.

#! perl -sw use strict; my %options = ( url => { required => 1, type => 'string', mask => qr/^(\S{1}.*?\S{1})$/io, map => sub { (my $arg = $_[0]) =~ s/(.*)/--url="$1" +/io; return $arg; }, default => undef, }, title => { required => 0, type => 'string', mask => qr/^(\S{1}.*?\S{1})$/io, map => sub { (my $arg = $_[0]) =~ s/(.*)/--title="$ +1"/io; return $arg; }, default => undef, }, AvantGo => { required => 0, type => 'boolean', mask => qr/^(0|1|y|n|yes|no|t|f|true|false)$/io, # NOTE: Longer option MUST come before shorter equ +ivalents in substitutions. maptrue => sub { (my $arg = $_[0]) =~ s/(1|y|yes|true|t +)/--avantgo/io; return $arg; }, mapfalse => sub { (my $arg = $_[0]) =~ s/(0|no|n|false|f)/- +-no_avantgo/io; return $arg; }, default => '--no_avantgo', }, maxdepth => { required => 1, type => 'numeric', mask => qr/^(\d+)$/, map => sub { (my $arg = $_[0]) =~ s/(\d+)/--maxdept +h=$1/o; return $arg; }, default => '--maxdepth=2', }, bbp => { required => 0, type => 'numeric', mask => qr/^(1|2|4|8|32)$/, map => sub { (my $arg = $_[0]) =~ s/(\d+)/--bbp=$1/ +o; return $arg; }, default => '--bbp=4', }, compression => { required => 1, type => 'numeric', mask => qr/^(zlib|zip|gzip|tar)$/i, map => sub { (my $arg = $_[0]) =~ s/(\w+)/--compres +sion=$1/io; return $arg; }, default => '--compression=zlib', }, no_url_info => { required => 0, type => 'boolean', mask => qr/^(0|1|y|n|yes|no|t|f|true|false)$/i, maptrue => sub { (my $arg = $_[0]) =~ s/(1|yes|y|true|t +)/--no_url_info/io; return $arg; }, mapfalse => sub { (my $arg = $_[0]) =~ s/(0|no|n|false|f)// +io; return $arg; }, default => '', }, beamable => { required => 0, type => 'boolean', mask => qr/^(0|1|y|n|yes|no|t|f|true|false)$/i, maptrue => sub { (my $arg = $_[0]) =~ s/(1|yes|y|true|t +)/--beamable/io; return $arg }, mapfalse => sub { (my $arg = $_[0]) =~ s/(0|no|n|false|f)/- +-not-beamable/io; return $arg; }, default => '--beamable', }, ); my @rawInput = <DATA>; my $pInput = parseInput( \@rawInput ); # builds and returns ref to has +h of input parameters my @exeArgs = (); my $fatalError = 0; *LOG = *STDERR; foreach my $option (keys %options) { print LOG 'Option ', $option; if( exists $pInput->{$option} ) { # the option was +present print LOG ' found: "'; if (defined $pInput->{$option}) { # and they suppli +ed a value print LOG $pInput->{$option}, '" '; if ( $pInput->{$option} =~ $options{$option}{mask} ) { #pa +sses the mask print LOG ' passed '; if ( $options{$option}{type} eq 'boolean' ) { # try and extract a true switch my $arg = $options{$option}{maptrue}( $pInput->{$o +ption} ); # extract a false switch if that failed $arg = $options{$option}{mapfalse}( $pInput->{$opt +ion} ) if ( $arg eq $pInput->{$option} ); print LOG $/, 'using switch "', $arg, '"', $/; push @exeArgs, $arg; } else { # type = string or numeric my $arg = $options{$option}{map}( $pInput->{$optio +n} ); print LOG $/, 'using switch "', $arg, '"', $/; push @exeArgs, $arg; } } else { # Handle supplied value invalid print LOG 'failed '; if ( $options{$option}{required} ) { # they must suppl +y a valid value print LOG 'request rejected', $/; warn "bad args\n"; $fatalError = 1; next; } else { my $arg = $options{$option}{default}; print LOG 'using default "', $arg, '"', $/; push @exeArgs, $arg; } } } else { # Handle defined key without value print LOG 'no value supplied '; if ( $options{$option}{required} ) { print 'required value not supplied, request rejected', + $/; warn "bad args\n"; $fatalError = 1; next; } else { my $arg = $options{$option}{default}; print 'using default "', $arg, '"', $/; push @exeArgs, $arg; } } } else { print LOG 'Required option ', $option, ' missing '; if ( $options{$option}{required} ) { # Handle missing required option print LOG '- rejecting request', $/; } else { my $arg = $options{$option}{default}; print LOG '- using default "', $arg, '"', $/; push @exeArgs, $arg; } } } if ( $fatalError ) { print LOG 'command not issued', $/; # do something about it. } else { # better handling here. print 'Issuing command with arguements:'.$/; print $_.$/ for @exeArgs; print LOG 'command returned: ', system( 'command', @exeArgs ); } exit; sub parseInput{ # Expecting a single parm die 'parseInput: Invalid parm(s) supplied'.$/ if @_ != 1 or ref($_ +[0]) ne 'ARRAY'; my ( $pRawInput ) = shift; my %input; $input{extraneous} = (); # set up an empty array for lines we cann +ot parse. for ( @{$pRawInput} ) { chomp; # print "'$_'\n"; my $keyseen = ''; if ( m/^\s*?(\S+)\s*?=\s*?(\S{1}.*?)$/ ) { # k +ey = somestuff \n $keyseen = $1; $input{$1} = $2 if $2; # a +(possibly partial) value found print "found key: '$1' value: '$2'\n"; } elsif ( m/^\s*?(\S+)\s*?=$/ ) { # key = \n + WARNING This regex not exercised!!!! $keyseen = $1; $input{$1} = ''; # no value + yet print "no value for key: '$keyseen' yet\n"; } elsif ($keyseen) { # $input{$keyseen} .= $_; # assume i +t part of the previous keys value print "Adding '$_' to the value of key: '$keyseen'\n"; } else { # line contains no key, and no key yet seen (or blank l +ine). push @{$input{extraneous}}, $_ if ! m/^$/; # discard blank +s print "Added '$_' to extraneuos array\n"; } } print "\nparsing completed \n\n"; return \%input; } __DATA__ url = http://www.wired.com/news_drop/palmpilot/ AvantGo = No maxdepth = 2 bpp = 4 compression = zlib title = Wired News no_url_info = True beamable = False

The following is a run on the limited test data supplied.

C:\test>perl 197724.pl found key: 'url' value: 'http://www.wired.com/news_drop/palmpilot/' found key: 'AvantGo' value: 'No' found key: 'maxdepth' value: '2' found key: 'bpp' value: '4' found key: 'compression' value: 'zlib' found key: 'title' value: 'Wired News' found key: 'no_url_info' value: 'True' found key: 'beamable' value: 'False' parsing completed Option maxdepth found: "2" passed using switch "--maxdepth=2" Option url found: "http://www.wired.com/news_drop/palmpilot/" passed using switch "--url="http://www.wired.com/news_drop/palmpilot/"" Option beamable found: "False" passed using switch "--not-beamable" Option title found: "Wired News" passed using switch "--title="Wired News"" Option bbpRequired option bbp missing - using default "--bbp=4" Option no_url_info found: "True" passed using switch "--no_url_info" Option AvantGo found: "No" passed using switch "--no_avantgo" Option compression found: "zlib" passed using switch "--compression=zlib" Issuing command with arguements: --maxdepth=2 --url="http://www.wired.com/news_drop/palmpilot/" --not-beamable --title="Wired News" --bbp=4 --no_url_info --no_avantgo --compression=zlib The system cannot execute the specified program. command returned: 256 C:\test>

Well It's better than the Abottoire, but Yorkshire!

In reply to Re: Cleansing and stacking arguments before calling system() by BrowserUk
in thread Cleansing and stacking arguments before calling system() by hacker

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post, it's "PerlMonks-approved HTML":



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, details, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, summary, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.