Rodster001 has asked for the wisdom of the Perl Monks concerning the following question:

Greetings,

I looked over perlretut and searched here, but didn't see an answer to this.

This regexp works:

$ENV{REQUEST_URI} =~ s#/Products/bt-(.*?).aspx#/s/Products/$1#i;
But what I want to do is this:

my $in = "/Products/bt-(.*?).aspx"; my $out = "/s/Products/$1"; $ENV{REQUEST_URI} =~ s#$in#$out#i;
How do I make that work? Am I missing a modifier?

Thanks for your help! (and sorry if an answer to this was in those links above, but I missed it).

Replies are listed 'Best First'.
Re: Using Regexp Patterns as Variables
by kyle (Abbot) on Mar 18, 2009 at 16:11 UTC

    This smells a little XY Problem to me since I can't see why you'd want to do that.

    That said, what's happening here is that the value of $1 is interpolated into $out at the time that you define $out. If you want, you can use single quotes to define out, and it will have the literal string "$1" in it, but that won't work either.

    You may be able to do this:

    my $out = '/s/Products/$1'; $ENV{REQUEST_URI} =~ s/$in/eval qq{"$out"}/ie;

    I can't say I recommend that, however, especially if you don't trust the source of your real $out.

    So what problem are you really trying to solve? What lead you to write code like this in the first place?

      You just allowed arbitrary code to be placed in the url. Considering the code appears in a CGI script, that doesn't seem to be a good idea.

      If you want a template (that's what '$1' is here), use a template, not eval EXPR!!!

        It's an admin function. I fully trust the source of where these rules are created. Regular users cannot do this and the function is well protected.

        Think of it like giving them root access. If root wants to do an "rm -rf /" that's the power of root.

        With great power comes great... well, you know.

        That's why I wrote this:

        I can't say I recommend that, however, especially if you don't trust the source of your real $out.

      I thought someone might ask.

      This code runs two sites, there is an admin function that allows site admins to create URL translators (old product links to new product links). Basically, they add patterns and those get stored in a database (it doesn't work yet though).

      I don't want to hard code the patterns (as both sites are very different) and also there needs to be a way to add these rules as broken links are found.

      Make sense? Code looks something like this:

      my $req = $ENV{REQUEST_URI}; ## Get rules my $query = qq~ SELECT incoming, outgoing, id FROM url_translate ~; my $sth = $dbh->prepare($query); my $rv = $sth->execute; while (my $r = $sth->fetchrow_hashref) { my $in = $r->{incoming}; my $out = $r->{outgoing}; # if( s#$in#$out#i ) { if( $req =~ s#/Products/bt-(.*?).aspx#/s/Products/$1#i + ) { $ENV{REQUEST_URI} = $req; return; } } return;
      This worked kyle:
      my $out = '/s/Products/$1'; $ENV{REQUEST_URI} =~ s/$in/eval qq{"$out"}/ie;
      I fully understand the security implications of doing this. But, as I mentioned the people creating these rules also have full access to the machine running the site. So as to say, it's a trusted source.

      Thanks for your help!

        What ikegami points out is also important to recognize. Anyone who can access to the site can feed in a URL with anything in it. As such, they may be able to choose a value for $1 with Dire Consequences.

        For example, $1 = q{";system('shutdown -h now');"}

Re: Using Regexp Patterns as Variables
by kennethk (Abbot) on Mar 18, 2009 at 16:10 UTC