#!%%LOCALBASE%%/bin/ruby
#
# tdiaryinstall.rb - tDiary user directory copy script
# Date created:                        13 July 2003
# Whom:                                KAMIYA Satosi  <mimoriso@gmail.com>

require 'getoptlong'
require 'etc.so'
require 'fileutils'
require 'find'
require 'tempfile'

# 
$OPT_TDIARYMASTER = "%%WWWDIR%%"
$OPT_TDIARYDOCDIR = "%%DOCSDIR%%"
$OPT_LANG         = '%%TDIARY_LANG%%'

def usage
  STDERR.print "Usage: #{File.basename($0)} [options]\n"
  STDERR.print "Options:\n"
  STDERR.print "    --help                    Display this information\n"
  STDERR.print "    --user=<username>         Specify user's login name\n"
  STDERR.print "    --diarydir=<diarydir>     Specify tDiary data directory default: diary\n"
  STDERR.print "    --httpdir=<httpdir>       Specify apache UserDirectory  default: public_html\n"
  STDERR.print "    --name=<author_name>      Specify author name\n"
  STDERR.print "    --mail=<author_mail>      Specify author mail address\n"
  STDERR.print "    --tdiarymaster=<dir>      Specify tDiary master directory default: %%WWWDIR%%\n"
  STDERR.print "    --tdiarydocdir=<docdir>   Specify tDiary document directory default: %%DOCSDIR%%\n"
  STDERR.print "    --lang=<language>         Specify your language ('en' or 'ja') default: %%TDIARY_LANG%%\n"
  STDERR.print "    --suexec                  Use suExec for CGI execution\n"
  STDERR.print "    --symlink                 Use symbolic link for tDiary master files\n"
  STDERR.print "    --quiet                   Do not display any information\n"
  STDERR.print "    --noop                    Do not install any file. Use this option with --verbose\n"
  STDERR.print "    --verbose                 Verbose; display verbose debugging messages.\n"
  exit 1
end

parser = GetoptLong.new
parser.set_options(
  ['--user',    '-u', GetoptLong::REQUIRED_ARGUMENT],
  ['--diarydir','-d', GetoptLong::REQUIRED_ARGUMENT],
  ['--httpdir' ,'-h', GetoptLong::REQUIRED_ARGUMENT],
  ['--name',    '-n', GetoptLong::REQUIRED_ARGUMENT],
  ['--mail',    '-m', GetoptLong::REQUIRED_ARGUMENT],
  ['--tdiarymaster' , GetoptLong::REQUIRED_ARGUMENT],
  ['--tdiarydocdir' , GetoptLong::REQUIRED_ARGUMENT],
  ['--lang'         , GetoptLong::REQUIRED_ARGUMENT],
  ['--suexec'       , GetoptLong::NO_ARGUMENT],
  ['--symlink', '-l', GetoptLong::NO_ARGUMENT],
  ['--quiet',   '-q', GetoptLong::NO_ARGUMENT],
  ['--noop'         , GetoptLong::NO_ARGUMENT],
  ['--verbose'      , GetoptLong::NO_ARGUMENT],
  ['--help'         , GetoptLong::NO_ARGUMENT])
begin
  parser.each_option do |name, arg|
    eval "$OPT_#{name.sub(/^--/, '').gsub(/-/, '_').upcase} = '#{arg}'"
  end
rescue
  raise "getoptlong"
end
usage() if defined?($OPT_HELP)

class TdiaryInstall
  attr_accessor :tdiarymaster
  attr_accessor :tdiarydocdir
  attr_accessor :lang
  attr_reader   :euid
  attr_accessor :username
  attr_accessor :diarydir
  attr_accessor :httpdir
  attr_reader   :passwd
  attr_accessor :fileutilOptions
  attr_accessor :author_name
  attr_accessor :author_mail
  attr_reader   :author_host
  def initialize
    @passwd   = Etc.getpwuid()
    @euid     = @passwd.uid
    @username =(@passwd.name)
    @diarydir = 'diary'
    @httpdir  = 'public_html'
    @fileutilOptions = {}
    @author_name = @passwd.gecos
    @author_host = "#{`hostname`.chomp}"
    @author_mail = "#{@username}@#{`hostname`.chomp}"
  end

  def username=(value)
    @username = value
    @passwd = Etc.getpwnam(@username)
    @author_name = @passwd.gecos
    @author_mail = "#{@username}@#{`hostname`.chomp}"
  end

  def lang=(value)
    case value
    when 'en'
      @lang = 'en'
    when 'ja'
      @lang = 'ja'
    else
      raise "Unknown Language : #{value}"
    end
  end

  def installAll
    raise "You can not use tDiary for superuser." if @passwd.uid == 0

    echo "************************************************************\n"
    echo "Starting tDiary for FreeBSD  user directory installation ...\n"
    prepareDirs()

    echo "Copy tDiary ...\n"
    if $OPT_SYMLINK then
      linkBaseFile()
    else
      copyBaseFile()
    end

    installConfig()
    setPermissions() if ! defined?($OPT_NOOP)

    echo "***\n"
    echo "You have to execute the following commands:\n"
    echo "    % /usr/local/sbin/htpasswd -c #{@passwd.dir}/.htpasswd #{@username}\n\n"
    echo "Please read #{@tdiarydocdir}/README.en.html\n"
    echo "    for additional information.\n"
    echo "************************************************************\n"
  end

  def prepareDirs
    if ! FileTest.exist?("#{@passwd.dir}/#{@diarydir}")
      FileUtils.mkdir_p("#{@passwd.dir}/#{@diarydir}", @fileutilOptions)
    end
    if ! FileTest.exist?("#{@passwd.dir}/#{@httpdir}/#{@diarydir}")
      FileUtils.mkdir_p("#{@passwd.dir}/#{@httpdir}/#{@diarydir}", @fileutilOptions)
    end
    if ! FileTest.exist?("#{@passwd.dir}/#{@httpdir}/#{@diarydir}/images")
      FileUtils.mkdir_p("#{@passwd.dir}/#{@httpdir}/#{@diarydir}/images", @fileutilOptions)
    end
    if ! FileTest.exist?("#{@passwd.dir}/#{@httpdir}/#{@diarydir}/tmp")
      FileUtils.mkdir_p("#{@passwd.dir}/#{@httpdir}/#{@diarydir}/tmp", @fileutilOptions)
    end
  end

  def linkBaseFile
    FileUtils.ln_s("#{@tdiarydocdir}", "#{@passwd.dir}/#{@httpdir}/#{@diarydir}/doc", @fileutilOptions)
    FileUtils.ln_s("#{@tdiarymaster}/Gemfile", "#{@passwd.dir}/#{@httpdir}/#{@diarydir}", @fileutilOptions)
    FileUtils.ln_s("#{@tdiarymaster}/app.json", "#{@passwd.dir}/#{@httpdir}/#{@diarydir}", @fileutilOptions)
    FileUtils.ln_s("#{@tdiarymaster}/benchmark", "#{@passwd.dir}/#{@httpdir}/#{@diarydir}", @fileutilOptions)
    FileUtils.ln_s("#{@tdiarymaster}/bin", "#{@passwd.dir}/#{@httpdir}/#{@diarydir}", @fileutilOptions)
    FileUtils.ln_s("#{@tdiarymaster}/index.fcgi", "#{@passwd.dir}/#{@httpdir}/#{@diarydir}", @fileutilOptions)
    FileUtils.ln_s("#{@tdiarymaster}/index.rb", "#{@passwd.dir}/#{@httpdir}/#{@diarydir}", @fileutilOptions)
    FileUtils.ln_s("#{@tdiarymaster}/js", "#{@passwd.dir}/#{@httpdir}/#{@diarydir}", @fileutilOptions)
    FileUtils.ln_s("#{@tdiarymaster}/lib", "#{@passwd.dir}/#{@httpdir}/#{@diarydir}", @fileutilOptions)
    FileUtils.ln_s("#{@tdiarymaster}/misc", "#{@passwd.dir}/#{@httpdir}/#{@diarydir}", @fileutilOptions)
    FileUtils.ln_s("#{@tdiarymaster}/package.json", "#{@passwd.dir}/#{@httpdir}/#{@diarydir}", @fileutilOptions)
    FileUtils.ln_s("#{@tdiarymaster}/theme", "#{@passwd.dir}/#{@httpdir}/#{@diarydir}", @fileutilOptions)
    FileUtils.ln_s("#{@tdiarymaster}/update.fcgi", "#{@passwd.dir}/#{@httpdir}/#{@diarydir}", @fileutilOptions)
    FileUtils.ln_s("#{@tdiarymaster}/update.rb", "#{@passwd.dir}/#{@httpdir}/#{@diarydir}", @fileutilOptions)
    FileUtils.ln_s("#{@tdiarymaster}/views", "#{@passwd.dir}/#{@httpdir}/#{@diarydir}", @fileutilOptions)
  end

  def copyBaseFile
    opts = @fileutilOptions.dup
    opts.store(:preserve, true)
    FileUtils.cp_r("#{@tdiarydocdir}", "#{@passwd.dir}/#{@httpdir}/#{@diarydir}/doc", opts)
    FileUtils.cp("#{@tdiarymaster}/Gemfile", "#{@passwd.dir}/#{@httpdir}/#{@diarydir}", @fileutilOptions)
    FileUtils.cp("#{@tdiarymaster}/app.json", "#{@passwd.dir}/#{@httpdir}/#{@diarydir}", @fileutilOptions)
    FileUtils.cp_r("#{@tdiarymaster}/benchmark", "#{@passwd.dir}/#{@httpdir}/#{@diarydir}", opts)
    FileUtils.cp_r("#{@tdiarymaster}/bin", "#{@passwd.dir}/#{@httpdir}/#{@diarydir}", opts)
    FileUtils.cp("#{@tdiarymaster}/index.fcgi", "#{@passwd.dir}/#{@httpdir}/#{@diarydir}", @fileutilOptions)
    FileUtils.cp("#{@tdiarymaster}/index.rb", "#{@passwd.dir}/#{@httpdir}/#{@diarydir}", @fileutilOptions)
    FileUtils.cp_r("#{@tdiarymaster}/js", "#{@passwd.dir}/#{@httpdir}/#{@diarydir}", opts)
    FileUtils.cp_r("#{@tdiarymaster}/lib", "#{@passwd.dir}/#{@httpdir}/#{@diarydir}", opts)
    FileUtils.cp_r("#{@tdiarymaster}/misc", "#{@passwd.dir}/#{@httpdir}/#{@diarydir}", opts)
    FileUtils.cp("#{@tdiarymaster}/package.json", "#{@passwd.dir}/#{@httpdir}/#{@diarydir}", @fileutilOptions)
    FileUtils.cp_r("#{@tdiarymaster}/theme", "#{@passwd.dir}/#{@httpdir}/#{@diarydir}", opts)
    FileUtils.cp("#{@tdiarymaster}/update.fcgi", "#{@passwd.dir}/#{@httpdir}/#{@diarydir}", @fileutilOptions)
    FileUtils.cp("#{@tdiarymaster}/update.rb", "#{@passwd.dir}/#{@httpdir}/#{@diarydir}", @fileutilOptions)
    FileUtils.cp_r("#{@tdiarymaster}/views", "#{@passwd.dir}/#{@httpdir}/#{@diarydir}", opts)
  end

  def installConfig
    tempfile = Tempfile.new("tdiary.conf.beginner")
    tempfile.write tdiaryConfReplace("#{@tdiarymaster}/tdiary.conf.beginner")
    tempfile.close
    FileUtils.cp(tempfile.path, "#{@passwd.dir}/#{@httpdir}/#{@diarydir}/tdiary.conf.beginner", @fileutilOptions)

    tempfile = Tempfile.new("tdiary.conf.sample")
    tempfile.write tdiaryConfReplace("#{@tdiarymaster}/tdiary.conf.sample")
    tempfile.close
    FileUtils.cp(tempfile.path, "#{@passwd.dir}/#{@httpdir}/#{@diarydir}/tdiary.conf.sample", @fileutilOptions)

    tempfile = Tempfile.new("tdiary.conf.sample-en")
    tempfile.write tdiaryConfReplace("#{@tdiarymaster}/tdiary.conf.sample-en")
    tempfile.close
    FileUtils.cp(tempfile.path, "#{@passwd.dir}/#{@httpdir}/#{@diarydir}/tdiary.conf.sample-en", @fileutilOptions)

    if ! FileTest.exist?("#{@passwd.dir}/#{@httpdir}/#{@diarydir}/tdiary.conf")
      FileUtils.cp("#{@passwd.dir}/#{@httpdir}/#{@diarydir}/tdiary.conf.sample", "#{@passwd.dir}/#{@httpdir}/#{@diarydir}/tdiary.conf", @fileutilOptions)
    end

    tempfile = Tempfile.new("dot.htaccess")
    tempfile.write dothtaccessReplace("#{@tdiarymaster}/dot.htaccess")
    tempfile.close
    FileUtils.cp(tempfile.path, "#{@passwd.dir}/#{@httpdir}/#{@diarydir}/dot.htaccess", @fileutilOptions)
    if ! FileTest.exist?("#{@passwd.dir}/#{@httpdir}/#{@diarydir}/.htaccess")
      FileUtils.cp("#{@passwd.dir}/#{@httpdir}/#{@diarydir}/dot.htaccess", "#{@passwd.dir}/#{@httpdir}/#{@diarydir}/.htaccess", @fileutilOptions)
    end
  end

  def setPermissions
    if (defined?($OPT_SUEXEC))
      FileUtils.chmod(0701, "#{@passwd.dir}/#{@diarydir}", @fileutilOptions)
      FileUtils.chmod(0701, "#{@passwd.dir}/#{@httpdir}/#{@diarydir}", @fileutilOptions)
      FileUtils.chmod(0604, "#{@passwd.dir}/#{@httpdir}/#{@diarydir}/.htaccess", @fileutilOptions)
      FileUtils.chmod(0700, "#{@passwd.dir}/#{@httpdir}/#{@diarydir}/index.fcgi", @fileutilOptions)
      FileUtils.chmod(0700, "#{@passwd.dir}/#{@httpdir}/#{@diarydir}/index.rb", @fileutilOptions)
      FileUtils.chmod(0700, "#{@passwd.dir}/#{@httpdir}/#{@diarydir}/update.fcgi", @fileutilOptions)
      FileUtils.chmod(0700, "#{@passwd.dir}/#{@httpdir}/#{@diarydir}/update.rb", @fileutilOptions)
    else
      FileUtils.chmod(0777, "#{@passwd.dir}/#{@diarydir}", @fileutilOptions)
      FileUtils.chmod(0777, "#{@passwd.dir}/#{@httpdir}/#{@diarydir}", @fileutilOptions)
      FileUtils.chmod(0644, "#{@passwd.dir}/#{@httpdir}/#{@diarydir}/.htaccess", @fileutilOptions)
      FileUtils.chmod(0755, "#{@passwd.dir}/#{@httpdir}/#{@diarydir}/index.fcgi", @fileutilOptions)
      FileUtils.chmod(0755, "#{@passwd.dir}/#{@httpdir}/#{@diarydir}/index.rb", @fileutilOptions)
      FileUtils.chmod(0755, "#{@passwd.dir}/#{@httpdir}/#{@diarydir}/update.fcgi", @fileutilOptions)
      FileUtils.chmod(0755, "#{@passwd.dir}/#{@httpdir}/#{@diarydir}/update.rb", @fileutilOptions)
    end
    FileUtils.chmod(0644, "#{@passwd.dir}/#{@httpdir}/#{@diarydir}/dot.htaccess", @fileutilOptions)

    if @euid == 0 then
      Find.find("#{@passwd.dir}/#{@diarydir}", "#{@passwd.dir}/#{@httpdir}/#{@diarydir}") do |f|
        File.chown(@passwd.uid, @passwd.gid, f)
      end
      if File::Stat.new("#{@passwd.dir}/#{@httpdir}").uid == 0
        File.chown(@passwd.uid, @passwd.gid, "#{@passwd.dir}/#{@httpdir}")
      end
    end
  end

  def echo(s)
    STDOUT.print s if ! defined?($OPT_QUIET)
  end

  def tdiaryConfReplace(filename)
    s = ''
    File.open(filename, "r:UTF-8") { |fp|
      fp.each { |line|
        line = "@data_path = '#{@passwd.dir}/#{@diarydir}'\n" if line =~ /^\@data_path\s/
        line = "@author_name = '#{@author_name}'\n" if line =~ /^\@author_name\s/
        line = "@author_mail = '#{@author_mail}'\n" if line =~ /^\@author_mail\s/
        line = "@html_title = '#{@author_name} diary'\n" if line =~ /^\@html_title\s/
        line = "@index_page = 'http://#{@author_host}/~#{@username}\/'" if line =~ /^\@index_page\s/
	line = "@lang = '#{@lang}'\n" if line =~ /^\@lang\s/
        s += line
      }
    }
    s
  end

  def dothtaccessReplace(filename)
    s = ''
    File.open(filename) { |fp|
      fp.each { |line|
        line = "\tAuthUserFile  #{@passwd.dir}/.htpasswd\n" if line =~ /^\s*AuthUserFile\s/
        line = "\tRequire user  #{@username}\n" if line =~ /^\s*Require user\s/
        line = "Options +FollowSymLinks\n" if line =~ /^\#Options \+FollowSymLinks/ && $OPT_SYMLINK
        s += line
      }
    }
    s
  end
end

tdiaryinst = TdiaryInstall.new
tdiaryinst.tdiarymaster = $OPT_TDIARYMASTER
tdiaryinst.tdiarydocdir = $OPT_TDIARYDOCDIR
tdiaryinst.lang = $OPT_LANG
tdiaryinst.username = $OPT_USER if defined?($OPT_USER)
tdiaryinst.diarydir = $OPT_DIARYDIR if defined?($OPT_DIARYDIR)
tdiaryinst.httpdir = $OPT_HTTPDIR if defined?($OPT_HTTPDIR)
tdiaryinst.author_name = $OPT_NAME if defined?($OPT_NAME)
tdiaryinst.author_mail = $OPT_MAIL if defined?($OPT_MAIL)
tdiaryinst.fileutilOptions.store(:noop, true) if defined?($OPT_NOOP)
tdiaryinst.fileutilOptions.store(:verbose, true) if defined?($OPT_VERBOSE)

tdiaryinst.installAll

exit 0
