Apache-RandomLocation

 view release on metacpan or  search on metacpan

RandomLocation.pm  view on Meta::CPAN

      my $host = lc $r->get_remote_host;
      if (( ! $host ) or ( $host =~ /^\d+\.\d+\.\d+\.\d+$/ )) {
	my $ip = $r->connection->remote_ip;
	$host = lc host_name($ip) || 'localhost';
      }
      my $country_code = country_code($host);
      my $site = get_site($country_code, $site_info);
      $url = "$site_info->{$site}[0]$site/$site_info->{$site}[2]${request}";
# redirect the client
      $r->send_cgi_header("Location: ${url}\015\012\015\012");
      return REDIRECT;
    }

# for testing purposes
#    $r->send_http_header;
#   $r->print($url);
#    return OK;

    
  }

}

# gets the country code, based on the domain name
sub country_code {
  my ($country_code) = @_;
  if (( $country_code =~ /^\d+\.\d+\.\d+\.\d+$/) or ($country_code !~ /\./) ){
    $country_code = '(com|edu|net|org|us)';
  }
  else {
    $country_code =~ s/.*\.(\w+)$/$1/;
    if (lc $country_code =~ /^(com|edu|net|org|us)$/) {
      $country_code = '(com|edu|net|org|us)';
    }
  }
  return $country_code;
}

# searches through all the available sites, and chooses a random
# one nearby. If one doesn't exist, a random site with country code
#  /^(com|edu|net|org|us)$/ is chosen
sub get_site {
  my ($country_code, $site_info) = @_;
  my (@sites, @all_sites);
  foreach my $host ( keys %{$site_info} ) {
    push @sites, $host if ($site_info->{$host}[1] =~ /^$country_code$/);
    if (!@sites) {
      push @all_sites, $host if ($site_info->{$host}[1] =~ /^(com|edu|net|org|us)$/);
    }
  }
  my $site;
  if (@sites) {
    $site = $sites[rand(@sites)];
  } 
  else {
    $site = $all_sites[rand(@all_sites)]
  }
  return $site;
}

# looks up the host name, if the ip address is given
sub host_name {
  my ($addr) = @_;
  my @b;
  
  if (@b = ($addr =~ /(\d+)\.(\d+)\.(\d+)\.(\d+)/)) {
    return scalar gethostbyaddr(pack('C4', @b), 2);
  }
  return 0;
}

# reads ConfigFile, putting the result in $site_info, which is
# then set to  $main::Apache::RandomLocation::site_info{$mirror}
# For files, $site_info is a reference to an array holding the list
# of files. For mirrors, $site_info is a reference to a hash of arrays,
# with the key being the site amd the array holding, in order, the 
# protocol, country code, and directory 
sub read_config {
  my ($r, $type, $mirror, $dir, $configfile) = @_;
  my $site_info;

  if ( ($type eq 'file') and (! $configfile) ) {
    if ( ! $dir ) {
      $r->log_error("Need to specify ConfigFile for an external BaseURL");
      return 0;
    }
    else {
      unless ( opendir(DIR, $dir)  ) {
	$r->log_error("Cannot read $dir: $!");
	return 0;
      }
      my @globs = grep {not -d and not /^\./} readdir DIR;
      unless ( closedir DIR ) {
	$r->log_error("error closing $dir: $!");
	return 0;
      }
      push @{$site_info}, @globs;
      
    }
    
  }

  else {
    
    unless ( open(FILE, $configfile)  ) {
      $r->log_error("Apache::RandomLocation: cannot read $configfile: $!");
      return 0;
    }
    my @res;
    while (<FILE>)  {
      chomp;
      next if /^\#/;
      next if /^\s*$/;
      
      if ( $type eq 'file' ) {
	my $line = (split)[0];
	if ( $line !~ m!^\s*/.*/\s*$!) {
	  push @{$site_info}, $line;
	}
	else {
	  (my $re = $_) =~ s!^\s*/(.*?)/\s*$!$1!;



( run in 2.102 seconds using v1.01-cache-2.11-cpan-39bf76dae61 )