in reply to Reg Ex : an odd error...

If you've got it to work by now, may I point out a couple of possible problems (if you deliberately glided over these issues in the interests of simplicity, I apologise in advance :).

(NB: I assume, for the sake of argument, that you are prompting a user to enter (a full filepath to) a directory, and then letting them do something with this directory unless it is on the 'banned' list.)

1. Windoze filenames are case-INsensitive. So as well as banning 'd:/perl' you need to ban 'D:/Perl', etc. This is of course easy to solve.

2. You generally need to check for the user entering 'd:/perl/' and 'd:/perl\' (or 'd:perl\\' etc) as well as 'd:/perl'. This is easy to solve too.

3. If there is any chance of you needing to ban the current directory (where the code is being executed) and/or its parent, you should check for the user entering '.' or '..' (best, probably, to put them in your 'banned' list).

4. Concerning the following lines of your code:

$folder =~ /^($bannedF[$_]).*/; return BANNED if ($1);

I'm not sure what it does. If it is simplified to:

return BANNED if $folder =~ /^($bannedF[$_]).*/;

the problem becomes more apparent, namely that if you ban for example 'c:/win', you are also banning folders such as 'c:/wings', 'c:/winter_weather' etc. One way to solve this would be to ban anything that starts with 'c:/win/' (having stripped out spurious trailing slashes as under point 2 above).

There are no doubt other 'security' problems than those listed above, and more checking of user input is certainly required. However, this is how I'd do it if security weren't a vital issue:

use strict; use warnings; # Global variables: use vars qw ( @BANNED $INC_SUBDIRS ); @BANNED = qw ( . .. c:/perl/progs c:/winnt/system32 d: ); $INC_SUBDIRS = 1; # change to 0 or '' to turn off print "Enter a full pathname: "; chomp ( my $dir = <> ); # Remove trailing slashes: $dir =~ s{[/\\]+$}{}g; ; print "Verboten!" and exit if is_banned( $dir ); # Just for testing: opendir DIR, $dir or die "can't opendir $dir: $!"; print "$_\n" for readdir DIR; closedir DIR; sub is_banned { my $folder = lc shift; # lc for lower case for ( @BANNED ) { return 1 if $folder eq $_; if ( $INC_SUBDIRS ) { return 1 if $folder =~ /^$_\//; } } }

hth

dave

Replies are listed 'Best First'.
Re: Re: Reg Ex : an odd error...
by Foggy Bottoms (Monk) on Aug 20, 2003 at 08:04 UTC
    Hi N_A_N,

    Thanks for all your ideas ! They've helped me quite a bit and I'm still working on the script...

    Here are a couple answers to your remarks :
    • First of all, I'm not prompting the user for a path : when a change occurs on the drive, a function returns the path where that change occured...
    • Yes I do need to check for capital letters - actually, I noticed when comparing 2 paths that were the same except for the drive letter - in one case I had c:\, in the other C:\. So I rewrote my if statement to if (uc($folder) eq uc($wantedF$_)).
    • Furthermore, as for the "c:/temp" and the "c:\temp" paths, I also rewrote a bit of code that searches for \\ and swaps it for \/ :
      while ($folder =~ /\\/) { $folder =~ s/\\/\//; }
    • You ask whether the current folder can be banned : yes it can but it's irrelevant. Banning in this case means not considering any changes happening in that folder, hence ignoring it. This is not a security issue...
    • As for the regex, yeah I must admit it, I totally missed it - don't know what I was thinking... Your version is the one intended. Thanks !
    Thanks so much for your help and time - it's been quite useful to me...
[Re: Reg Ex : an odd error...] New Code
by Foggy Bottoms (Monk) on Aug 20, 2003 at 12:48 UTC
    Here's my latest code up-to-date cleaned-up and functional...

    sub compareFolder { my $folder = shift; $folder = uc ($folder); while ($folder =~ /\\/) { $folder =~ s/\\/\//; # transform regular c:\sample\path into c:/ +sample/path for later comparison } my $mode = shift; my @wantedF = @{+shift}; my @bannedF = @{+shift}; for (0..$#wantedF) { return ACCEPTED if ($folder eq uc($wantedF[$_])); # if folder is + directly equal to a desired(forced) folder } for (0..$#bannedF) { return BANNED if ($folder eq uc($bannedF[$_])); # if folder is + directly equal to a banned folder if ($mode == INC_SUBDIRS) # if a parent folder is banned then so + are the subfolders unless otherwise stated { my $bFolder = uc($bannedF[$_]); return BANNED if ($folder =~ /(^$bFolder\/).*/); # example : +$folder = c:\temp\one; $bannedF[$_] = c:\temp } } return ACCEPTED; # if execution reaches this point, then folder isn +'t affected by the forced/banned folder list # hence it can be scanned. }

    Thanks for your help and insight...