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

Hello Monks,

I have this problem: I have got a web app but I need to run it from normal user accounts instead of the webroot. For example, instead of going to http://server.com/cgi-bin/app.pl the user must go to http://server.com/~username/cgi-bin/app.pl
Since this code will be migrated around a lot, to a lot of different kinds of systems, I need a good way of finding the username to put in the url (for linking to other pages in the app).

Thankfully, I have got two scalars from which this information can be extracted. I have one that holds the path to a directory in the user's cgi-bin directory and another that holds the path to a directory inside of the user's public_html (or whatever it is called) directory.

Finally, getting to the question at hand.
How would you extract "username" from these examples:

  • /home/username/public_html/cgi-bin/dir and /home/username/public_html/directory
  • /Users/people/username/html/cgi-bin/directory and /Users/people/username/html/dirrr
  • /Home/username/public/cgi-bin/place and /Home/username/public/directory
  • /export/home/username/www/cgi-bin/dir and /export/home/username/www/directory
    I hope you get the idea....

    I haven't the slightest clue where to start beyond comparing the two strings and seeing where they differ, and removing those..... I am just really unsure.


    jcpunk
    all code is tested, and doesn't work so there :p (varient on common PM sig for my own ammusment)
    • Comment on Matching a string that you do not have any really good information about
  • Replies are listed 'Best First'.
    Re: Matching a string that you do not have any really good information about
    by Belgarion (Chaplain) on Apr 20, 2004 at 21:45 UTC

      You do have some information. It would appear that you have four different locations a path could be present in. The following code uses that knowledge to pull out the user name from the proper location.

      # Offsets into the path my %indexes = (home => 1, Users => 2, Home => 1, export => 2); # This would be one of the scalars you have access to (I'm using the # CGI-BIN one in this code.) my $path = '/home/username/public_html/cgi-bin/dir'; # Remove the leading / and then split up my @pieces = split('/', substr($path, 1)); # Extract the user name information my $username = $pieces[$indexes{$pieces[0]}]; print "$username\n";

      The %indexes variable holds the first part of the path as the key, and then the zero-based offset where the user name is stored after the path has been split.

    Re: Matching a string that you do not have any really good information about
    by saskaqueer (Friar) on Apr 20, 2004 at 22:33 UTC

      Just using the first set of paths, here's a solution:

      use strict; my @types = ( qr!^/[hH]ome/([^/]+)!, qr!^/Users/people/([^/]+)!, qr!^/export/home/([^/]+)! ); while (my $path = <DATA>) { my ($user) = map { $path =~ $_ ? $1 : () } @types; print $user, $/; } __DATA__ /home/user1/public_html/cgi-bin/dir /Users/people/user2/html/cgi-bin/directory /Home/user3/public/cgi-bin/place /export/home/user4/www/cgi-bin/dir
    Re: Matching a string that you do not have any really good information about
    by shemp (Deacon) on Apr 20, 2004 at 22:41 UTC
      In all the examples, i notice that in the path, the username immediately follows either 'home', ('Home'), or 'people', so you could use that, if this is always the case. If so, you could do something like this:
      ... # assume $path is initialized to a path youd like to parse. $path =~ s/^\///; my @parts = split /\//, $path; my $prepath_found = 0; my $username; my $name_taken = 0; foreach my $part (@parts) { if ( $prepath_found == 1 ) { if ( $name_taken ) { die 'serious dain brammage'; } $username = $part; $name_taken = 1; $prepath_found = -1; } if ( $part =~ /^[H|h]ome|people$/ ) { $prepath_found = 1; } } if ( ! defined $username ) { die 'invalid path'; }
      I guess it depends on how much checking you want to do, and how clearly defined your path info is.
      Also this could be written much more tersely, thought i'd be nice today :)
    Re: Matching a string that you do not have any really good information about
    by TilRMan (Friar) on Apr 21, 2004 at 05:08 UTC

      Perhaps you already have the information you need. If the CGI script (file) is owned by the user, then you can stat $0 to find it.

      #!/usr/bin/perl -wT use strict; use CGI; use File::stat; my $q = new CGI; my $url = $q->url(); my $file = $0; my $stat = stat $file; my $uid = $stat->uid; my $user = getpwuid($uid); print $q->header; print << "--"; <html><head><head><body><pre> URL is $url File is $file UID is $uid Username is $user </pre></body></html> --
    Re: Matching a string that you do not have any really good information about
    by greenFox (Vicar) on Apr 21, 2004 at 07:24 UTC
      Is there any reason not to use relative URL's? That way it should also work in any directory locations you haven't thought of.

      --
      Do not seek to follow in the footsteps of the wise. Seek what they sought. -Basho