#!/usr/bin/perl

use strict;
use warnings;
use lib qw(/root/usr/share/perl/5.12.4/);
use Data::Dumper;
use File::Slurp;
use DBI;
use Proc::ProcessTable;
use MySQL::Config qw(parse_defaults);

## version string
my $omeka='omeka-1.4.1';

## common part of configuration for all apache users
my $base_conf='';
$base_conf.="  Options +FollowSymLinks\n";
$base_conf.="  AllowOverride all\n";
$base_conf.="  order allow,deny\n";
$base_conf.="  allow from all\n";
$base_conf.="</Directory>\n";

## common part of configuration for mysql
my $my_cnf_start='';
$my_cnf_start.="# generated by install_omeka\n"; 
$my_cnf_start.=" [client]\n";

## main db open
my $dbh=&open_mysql();

## download the omeka zip file
my $url='http://omeka.org/files/'.$omeka.'.zip';
if(not -f "/tmp/$omeka.zip") {
  system("lynx -source $url > /tmp/$omeka.zip");
}
else {
  print "found /tmp/$omeka.zip, not downloading\n";
}

## work with user/password file
my $in_file=$ARGV[0];
if(defined($in_file) and -f $in_file) {
  ## read the passwords file, # are comments in it
  my $passwords=&get_passwords($in_file) or die;
  print Dumper $passwords;
  &install_for_all($passwords);
  exit;
}
## work with user
elsif(-d "/home/$in_file/$omeka") {
  my $user=$in_file;
  my $secret='';
  print "reinstalling for user $user\n";
  my $password=`grep password /home/$user/omeka/db.ini`;
  chomp $password;
  $password=~s|\s*password\s*=\s*["']([^"']+)["']|$1| or die "could not get password for $user\n";
  &remove_omeka_tables($user);
  ## delete files
  system("rm -rf /home/$user/$omeka");
  ## main install 
  system("unzip /tmp/$omeka.zip -d /home/$user > /dev/null");
  system("chown -R $user.$user /home/$user/$omeka");
  &customize_omeka($user,$password);
}
else {
  print "nothing to do\n";
}
$dbh->disconnect;

############################


sub remove_omeka_tables {
  my $user=shift;
  $dbh->do("use $user;");
  my $sth_show=$dbh->prepare("show tables");
  my $rv=$sth_show->execute();
  while(my $row = $sth_show->fetchrow_arrayref) {
    my $table=$row->[0];
    if(not $table=~m|^omeka_|) {
      next;
    }
    $dbh->do("drop table $table");
  }
}

## only done first time script ever runs
my $apache_omeka_dir="/etc/apache2/sites-available/omeka";
if(-d "/etc/apache2" and not -d $apache_omeka_dir) {
  system("mkdir $apache_omeka_dir");
  system("ln -s $apache_omeka_dir /etc/apache2/sites-enabled/omeka");
}

sub install_for_all {
  my $passwords=shift;
  ## main function, installation for all users
  foreach my $user (keys %{$passwords}) {
    my $secret=$passwords->{$user};
    ## is this an upgrade?
    my $upgrade=0;
    if(-l "/home/$user/omeka") {
      $upgrade=1;
    }
    &install_omeka($user,$secret,$upgrade);
  }
  $dbh->disconnect;
  ## restart apache
  &restart_web_servers();
}


##### the end #####

## install omeka for a user
sub install_omeka {
  my $user=shift;
  my $secret=shift;
  my $upgrade=shift;
  print "user is $user\n";
  if(-d "/home/$user/$omeka") {
    print "/home/$user/$omeka is already there, skipping\n";
    return;
  }
  ## main install 
  system("unzip /tmp/$omeka.zip -d /home/$user > /dev/null");
  system("chown -R $user.$user /home/$user/$omeka");
  ## create the database on creation, or copy old datafiles
  if(not $upgrade) {
    $dbh->do("CREATE DATABASE $user;");
    $dbh->do("grant all on $user.* to '$user'\@'localhost' identified by '$secret' with grant option;");
    ## while not strictly necessary, let us create a .my.cnf
    my $my_cnf_file="/home/$user/.my.cnf";
    my $my_cnf=$my_cnf_start;
    $my_cnf.="user     = $user\n";
    $my_cnf.="password = $secret\n";
    write_file($my_cnf_file,$my_cnf);
    system("chown $user.$user $my_cnf_file");
    system("chmod 600 $my_cnf_file");
  }
  else {
    ## copy old archive
    system("cp -ra /home/$user/omeka/archive/ /home/$user/$omeka/.");
    ## remove old symlink
    system("rm -r /home/$user/omeka");
  }
  &customize_omeka($user,$secret);
  ## make apache configuration
  my $conf_dir="/etc/apache2/sites-available/omeka";
  my $out_file="$conf_dir/$user".'_omeka';
  my $conf="Alias /omeka/$user/ /home/$user/$omeka/\n";
  $conf.="<Directory /home/$user/$omeka/>\n";
  $conf.=$base_conf;        
  &write_file($out_file,$conf);
  ## make synlink in the home directory 
  system("cd /home/$user ; ln -s $omeka omeka");
  ## make web synlink for omeka, I don't know why we need this
  system("rm -f /var/www/omeka/$user");
  system("cd /var/www/omeka ; ln -s /home/$user/$omeka $user");
}  

## gets the user/password hash from file
sub get_passwords {
  my $in_file=shift;
  my $omeka_conf=read_file($in_file);
  my $passwords;
  foreach my $line (split(/\n/,$omeka_conf)) {
    ## hash marks comments
    chomp $line;
    if($line=~m|^\s*#|) {
      print "not dealing with commented password line '$line'\n";
      next;
    }
    ## remove starting blanks
    $line=~s|^\s+||;
    my @data=split(/ +/,$line);
    $passwords->{$data[0]}=$data[1];
  }
  return $passwords;
}

sub customize_omeka {
  my $user=shift;
  my $secret=shift;
  ## customize the db.ini file for the user
  my $db_file="/home/$user/$omeka/db.ini";
  my $db_config=read_file($db_file); 
  $db_config=~s|host *= *\"[^\"]+\"|host=\"localhost\"|;
  $db_config=~s|username *= *\"[^\"]+\"|username=\"$user\"|;
  $db_config=~s|password *= *\"[^\"]+\"|password=\"$secret\"|;
  $db_config=~s|dbname *= *\"[^\"]+\"|dbname=\"$user\"|;
  write_file($db_file,$db_config);
  ## set up the web permissions
  my ($file,$before,$after);
  ##  this is really horrible!
  system("chmod -R 777 /home/$user/$omeka/archive");
  ##  rewrite base has to change for our setup
  $before='# RewriteBase /';
  $file="/home/$user/$omeka/.htaccess";
  $after="RewriteBase /omeka/$user";
  my $system;
  $system="sed -i 's|$before|$after|' $file";
  #print "$system\n";
  if(-f $file) {
    system($system);
  }
  $before='# RewriteBase /install/';
  $file="/home/$user/$omeka/install/.htaccess";
  $after="RewriteBase /omeka/$user/install";
  $system="sed -i 's|$before|$after|' $file";
  #print "$system\n";
  if(-f $file) {
    system($system);
  }
}


## open mysql
sub open_mysql {
  my %cfg = parse_defaults "my", qw(client);
  my $dbh = DBI->connect("DBI:mysql:", $cfg{'user'}, $cfg{'password'}) or die;
  my $sth = $dbh->prepare("SET collation_connection = utf8_general_ci");
  my $rv = $sth->execute();
  return $dbh;
}



## what web servers?
sub find_web_servers {
  my $t = new Proc::ProcessTable( 'cache_ttys' => 1 );
  my @web_servers=('apache2','lighttpd');
  my $web_servers;
  foreach my $p (@{$t->table}){
    my $prog=$p->exec or next;
    foreach my $server (@web_servers) {
      if($prog=~m|$server|) {
        $web_servers->{$server}=1;
      }
    }
  }
}

sub restart_web_servers {
  my $web_servers=shift // '';
  if(not $web_servers) {
    $web_servers=&find_web_servers();
  }
  foreach my $server (keys %$web_servers) {
    system("/etc/init.d/$server restart");
  }
}

