#!/usr/bin/perl

# Authors:
#
# Philippe Bourdin
# http://www.Bourdin.ch/Philippe/

$defaultpattern = "*.(html?|php3?|inc)";
$defaultdirectory = ".";

$recursive = 0;
$testonly = 0;
$backup = 0;

$found = 0;
$nothing = 0;

$pattern = $defaultpattern;
$startdirectory = $defaultdirectory;

while ($ARGV[0] =~ /^-/) {

  $argument = uc (shift ());
  if ($argument eq "-R") { $recursive = 1; }
  elsif ($argument eq "-T") { $testonly = 1; }
  elsif ($argument eq "-B") { $backup = 1; }
  elsif ($argument eq "-P") {
    $pattern = shift();
    if (!$pattern) { &usage ("No Pattern given ..."); }
    $pattern =~ s/\#\?/\*/g;
    $pattern =~ s/\*\*+/\*/g;
  }
  elsif ($argument eq "-D") {
    $startdirectory = shift();
    if (!$startdirectory) { &usage ("No Directory given ..."); }
    $startdirectory =~ s/\*+//g;
    $startdirectory =~ s/\/+$//;
  }
  else {
    &usage ("Option \"".$argument."\" unkown ...");
  }
}

if ($startdirectory ne "") {
  if ($startdirectory eq ".") { $startdirectory = ""; }
  elsif ($startdirectory !~ /\/$/) { $startdirectory .= "/"; }
}

$search = shift ();
if (!$search) { &usage ("Wrong amount of arguments ..."); }

$replace = shift ();
if (!$replace) { &usage ("Wrong amount of arguments ..."); }

$options = shift ();
$options =~ s/g//gi;

if (shift()) { &usage ("Wrong amount of arguments ..."); }

$regexp = "s/".$search."/".$replace."/".$options;
$replacecode = "while (\$out =~ ".$regexp.") { \$count++ } ;";

print "Executing ".$regexp."\n";

&subdir($startdirectory);

if (($found == 0) && ($nothing == 0)) {
  print 'Sorry, there were no files that matched the pattern "'.$startdirectory.$pattern.'" !'."\n";
}
elsif ($found == 0) {
  if ($testonly == 1) {
    print "Sorry, $nothing files matched the pattern, but the search-string hasn't been found.\n"
  }
  else {
    print "Sorry, $nothing files matched the pattern, but no replacements have been done.\n"
  }
}
elsif ($nothing == 0) {
  if ($testonly == 1) {
    print "All ".$found." files that matched the pattern contained the search-string.\n";
  }
  else {
    print "All ".$found." files that matched the pattern have been processed.\n";
  }
}
else {
  if ($testonly == 1) {	
    print "Finished. ".$found." of ".($found + $nothing)." matching files contained the search-string.\n";
  }
  else {
    print "Finished. ".$found." of ".($found + $nothing)." matching files have been processed.\n";
  }
}

exit;


sub subdir {

  my $directory = $_[0];

  my $filename = "";

  my $out;
  my $line;
  my $count;
  my $save;

  if ($directory ne "") {
    if ($directory eq ".") { $directory = ""; }
    elsif ($directory !~ /\/$/) { $directory .= "/"; }
  }
  
  my @dirlist = glob ($directory."*");
  my @filelist = glob ($directory."*");

  if (($recursive == 1) && ($#dirlist > 0)) {
    foreach $filename (@dirlist) {
      if (-d $filename) { &subdir ($filename); }
    }
  }

  foreach $filename (@filelist) {

    if (-d $filename) { next; }
    $testfile = "\$filename !~ /".$directory.$pattern."/";
    if (eval $testfile) { next; }

    $out = "";
    open (FILE, $filename);
    while (defined ($line = <FILE>)) { $out .= $line; }
    close (FILE);

    if (($backup == 1) && ($testonly == 0)) { $save = $out; }

    $count = 0;
    eval ($replacecode);
    die "Error: $@\n" if $@;

    if ($count > 0) {

      if (($backup == 1) && ($testonly == 0)) {
	open (FILE, "> ".$filename.".bak");
	print FILE $save;
	close (FILE);
      }

      $found++;
      print "$filename\tfound $count times";
      if ($testonly == 0) {
	print " ... ";
	open (FILE, "> ".$filename);
	print FILE $out;
	close (FILE);
	print "done.";
      }
      print "\n";
    }
    else {
      $nothing++;
    }
  }
  return;
}


sub usage {

  my $message = $_[0];

  print "\nSorry, ".$message."\n\n";
  print "Usage:\tperl Changer.pl [-r] [-b] [-t] [-d Directory] [-p Pattern] RegExp Replacement [RegExp-Options]\n\n";
  print "\t-r = Recursive - descent into directories\n";
  print "\t-b = Backup - creates .bak files\n";
  print "\t-t = Test only - doesn't write anything to disk\n";
  print "\t-d = Directory to start with - default is ".$defaultdirectory."\n";
  print "\t-p = Pattern to match - default is ".$defaultpattern."\n\n";
  print "Example:\n";
  print "\tChanger.pl -r -d pages -p \"in*.(html?|php|inc)\" \"abc(.*?)efg\" abcdefg gi\n";
  print "This recursively collects all files in the directory \"pages\" starting with\n";
  print "\"in\" and ending with \".html\",\".htm\",\".php\" or \".inc\" and then searches all\n";
  print "strings starting with \"abc\" and ending with \"efg\" by ignoring the case and\n";
  print "then replaces all those with \"abcdefg\" as often as this appears in one line.\n";
  print "Attention: Without the \"-t\"-option, the original files will be overwritten !\n\n";
  exit;
}

