#!/usr/bin/ruby
#
# Download updated flashplugins from Macromedia website.
#
# (C) 2002 Takuo KITAME <kitame@debian.org>
# You may freely distribute this file under the terms of the GNU General
# Public License, version 2 or later.
#
# $Id: update-flashplugin,v 1.1 2003/03/07 07:45:25 takuo Exp $

require 'net/http'
require 'md5'
require 'ftools'
require 'uri'
require 'getoptlong'
require '/etc/update-flashplugin.conf'

module UpdateFlashPlugin
include UpdateFlashPluginConf

class FlashUpdater
  attr_accessor :del, :local, :dir, :force, :check_only, :need_update
  attr_accessor :proxy, :no_proxy, :quiet
  def initialize
    @version = "7.0.25"
    @check_only = false
    @force = false
    @need_update = false
    @tar_sum = "  3de1fafb338dd82f1de596e8a3b31344"
    @instdir = "/usr/lib/flashplugin-nonfree"
    @checks = {
      "libflashplayer.so" => "48b908ecac3b305d4eae6a66ae3fb4dd",
      "flashplayer.xpt" => "a81fd3b03b8c6d6e5a14298110718d3f"
    }
    @linkdir = [ "/usr/lib/mozilla/plugins",
      "/usr/lib/mozilla-snapshot/plugins",
      "/usr/lib/mozilla-firebird/plugins",
      "/usr/lib/mozilla-firefox/plugins"
    ]
    @quiet = false
    @del = false
    @local = false
    @dir = "/tmp"
	@cur_dir = Dir.pwd
	@proxy_user = nil
	@proxy_uri = nil
	@mirrors = UpdateFlashPlugin::SITES
  end
  
  def _print(*str)
    print *str unless @quiet
  end
  
  def check_sum()
    if File.exist?(@instdir) && ! File.directory?(@instdir)
      $stderr.print "E: File is not directory: #{@instdir}.\n"
      clean_tmp
      exit 1
    elsif ! File.exist?(@instdir) 
      Dir.mkdir(@instdir)
    end
    print "Checking md5sum...\n"
    @checks.each { |f,s|
      if ! File.exist?("#{@instdir}/#{f}")
	_print "#{@instdir}/#{f} doesn't exist. Update\n"
	return true 
      end
      if MD5.new(File.open("#{@instdir}/#{f}", 'r').binmode.read).hexdigest != s
	_print "#{@instdir}/#{f} is outdated (didn't match md5sum). Update.\n"
	return true
      end
    }
    _print "flashplugins don't need updating.\n "
    return false
  end
  
  def tempdir(tmpdir = "/tmp", base = "", max = 100)
    n = 0
    while true
      begin
        tmpname = sprintf('%s/%s%d.%d', tmpdir, base, $$, n)
        unless File.exist?(tmpname)
          Dir.mkdir(tmpname)
          break
        end
      rescue
        raise "cannot generate tempdir `%s'" % tmpname if n >= max
	exit 1
      end
      n += 1
    end
    @tmpdir = tmpname
  end

  def check_proxy()
	return true if @proxy_uri
    if !@no_proxy && (@proxy || ENV["http_proxy"])
      proxy_str = @proxy || ENV["http_proxy"] || nil
      if proxy_str
		uri = URI::parse(ENV["http_proxy"])
		@proxy_user = ["#{uri.userinfo}"].pack('m').strip
		@proxy_uri = uri
		return true
      end
    end
	@proxy_uri = nil
	@proxy_user = nil
	return false
  end

  def get_file( host )
    # http://macromedia.mplug.org/tarball/debian/install_flash_player_7_linux.tar.gz
    dest = ""
    header = {}
    
    fp = open("#{@tmpdir}/install_flash_player_7_linux.tar.gz", "w+")
	failed = false
    path = @mirrors[host]
    if check_proxy
      header['Proxy-Authorization'] = "Basic " + @proxy_user if @proxy_user
      http = Net::HTTP::new(host, 80, 
                            @proxy_uri.host, @proxy_uri.port)
    else
      http = Net::HTTP::new(host)
    end
    begin
      r = http.head("#{path}install_flash_player_7_linux.tar.gz", header)
    rescue Errno::ECONNREFUSED
      $stderr.print "E: Connection was refused: #{host}\n"
      fp.close
      failed = true
    rescue Errno::EHOSTUNREACH
      $stderr.print "E: No route to host: #{host}\n"
      fp.close
      failed = true
    rescue TimeoutError
      $stderr.print "E: Connection has been timed out: #{host}\n"
      fp.close
      failed = true
    rescue
      $stderr.print "E: Unknown HTTP error: #{host}\n"
      fp.close
      failed = true
    end
	if failed
	  clean_tmp(true)
	  exit 1
	end
    t = r['content-length'].to_i
    c = 0
    http.get("#{path}install_flash_player_7_linux.tar.gz", header) { |d| 
      c = c + d.length
      p = sprintf("%.0f", c.to_f / t.to_f * 100)
      _print "getting install_flash_player_7_linux.tar.gz [", c, "/", t, " (", p, "%)]\r"
      fp.print d
    }
    _print "\n"
    fp.close
  end
  
  def extract()
    Dir.chdir(@tmpdir)
    if @local
      file = @dir + "/install_flash_player_7_linux.tar.gz"
      if !File.exist?(file)
		$stderr.print "E: File: #{file} does not exist.\n"
		Dir.chdir(@cur_dir)
		exit 1
      end
      if MD5.new(File.open("#{file}", 'r').binmode.read).hexdigest != @tar_sum
		$stderr.print "E: md5sum of #{file} does not match with #{@tar_sum}.\n"
		Dir.chdir(@cur_dir)
		exit
      end
      _print "use existing file: #{file}\n"
    else
      file = "install_flash_player_7_linux.tar.gz"
    end
    system("tar -xzf #{file} install_flash_player_7_linux/libflashplayer.so")
    system("tar -xzf #{file} install_flash_player_7_linux/flashplayer.xpt")
	Dir.chdir(@cur_dir)
  end
  
  def links()
    _print "Removing old plugin files, and creating symlinks to new.\n"
    @linkdir.each { |d|
      File.makedirs(d)
      @checks.each { |f,s|
	File.delete("#{d}/#{f}") if File.exist?("#{d}/#{f}")
	File.symlink("#{@instdir}/#{f}", "#{d}/#{f}")
      }
    }
  end
  
  def uninstall
    _print "Removing plugin files and symlinks...\n"
    @checks.each { |f,s|
      @linkdir.each { |d|
		File.delete("#{d}/#{f}") if File.exist?("#{d}/#{f}")
      }
      File.delete("#{@instdir}/#{f}") if File.exist?("#{@instdir}/#{f}")
    }
	File.delete("#{@instdir}/version") if File.exist?("#{@instdir}/version")
    Dir.delete(@instdir) if File.exist?(@instdir)
  end
  
  def install
    Dir.chdir("#{@tmpdir}/install_flash_player_7_linux")
    File.makedirs(@instdir)
    File.install("libflashplayer.so", "#{@instdir}/libflashplayer.so")
    File.install("flashplayer.xpt", "#{@instdir}/flashplayer.xpt")
    Dir.chdir(@cur_dir)
  end
  
  def update( host )
    _print "Updating flashplugin...\n"
	tempdir("/tmp","flashupdater",100)
    get_file( host ) unless @local
    extract()
    install()
    links()
    
    _print "done.\n"
    clean_tmp(false)
    done_update
  end

  def done_update
	file = @instdir + "/version"
	fp = File.open(file, "w+")
	fp.print @version, "\n"
	fp.print @tar_sum, "\n"
	fp.close
  end

  def check_installed
	file = @instdir + "/version"
	if File.exist?(file)
	  fp = File.open(file, "r")
	  @version = fp.gets.chomp
	  @tar_sum = fp.gets.chomp
	  fp.close
	else
	  @version = "not installed"
	end
  end

  def check_update()
	# check http://macromedia.mplug.org/tarball/debian/gpg-md5sums.txt
	_print "Checking new upstream release...\n"
	header = {}
	version = nil
	tar_sum = nil
	failed = true
    find = nil
	@mirrors.each { | host, path |
	  if failed
		failed = false
	  else
		break
	  end
	  if check_proxy
		header['Proxy-Authorization'] = "Basic " + @proxy_user if @proxy_user
		http = Net::HTTP::new(host, 80, 
							  @proxy_uri.host, @proxy_uri.port)
	  else
		http = Net::HTTP::new(host)	  
	  end
	  _print "I: checking http://#{host}#{path}...\n"
	  begin
		r , body = http.get("#{path}gpg-md5sums.txt", header)
		body.each { |l|
		  if /^flash-plugin ([\d\.]*)$/ =~ l
			version = $1
			next
		  elsif /^([0-9a-z]{32})\s+install_flash_player_7_linux.tar.gz$/ =~ l
			tar_sum = $1
			next
		  end
		}
        find = host
	  rescue Errno::ECONNREFUSED
		$stderr.print "E: Connection was refused: #{host}\n"
		failed = true
		next
	  rescue Errno::EHOSTUNREACH
		$stderr.print "E: No route to host: #{host}\n"
		failed = true
		next
	  rescue TimeoutError
		$stderr.print "E: Connection has been timed out: #{host}\n"
		failed = true
		next
	  rescue
		$stderr.print "E: Unknown HTTP error: #{host}\n"
		failed = true
		next
	  end
	}
	if failed 
	  $stderr.print "E: All failed.\n"
	  clean_tmp(true)
	  exit 1
	end
    if version && @version != version
      print "New version #{version} is detected (current: #{@version})\n"
      @version = version
      @tar_sum = tar_sum
      if @check_only
		_print "Do without \"-c\" option to upgrade.\n"
      else
		@need_update = true
      end
	else
	  _print "No new version is detected. (#{version} = #{@version})\n"
    end
    return find
  end  
  
  def clean_tmp(error = false)
    @checks.each {|f,s|
      File.delete("#{@tmpdir}/install_flash_player_7_linux/#{f}") if File.exist?("#{@tmpdir}/install_flash_player_7_linux/#{f}")
    }
    
    if error and File.exist?("#{@tmpdir}/install_flash_player_7_linux.tar.gz")
      File.delete("#{@tmpdir}/install_flash_player_7_linux.tar.gz")
    end

    if @del
      if @local
	File.delete("#{@dir}/install_flash_player_7_linux.tar.gz") if
	  File.exist?("#{@dir}/install_flash_player_7_linux.tar.gz")
      else
	File.delete("#{@tmpdir}/install_flash_player_7_linux.tar.gz") if
	  File.exist?("#{@tmpdir}/install_flash_player_7_linux.tar.gz")
      end
    else
      if ! @local and ! error
	_print "install_flash_player_7_linux.tar.gz was saved into #{@tmpdir}\n"
      end
    end
    if ! error
      Dir.delete("#{@tmpdir}/install_flash_player_7_linux") if
		File.exist?("#{@tmpdir}/install_flash_player_7_linux") &&
		File.directory?("#{@tmpdir}/install_flash_player_7_linux")
      Dir.delete(@tmpdir) if
		File.exist?(@tmpdir) &&
		File.directory?(@tmpdir) && (@del || @local)
    end
  end
end
end # module
##
## __MAIN__
##
if Process.uid != 0 
  print "You are not root.\n"
  exit 1
end

opt = GetoptLong.new
opt.set_options(
		['--uninstall', '-u', GetoptLong::NO_ARGUMENT],
		['--local-file', '-l', GetoptLong::REQUIRED_ARGUMENT],
		['--proxy', '-p', GetoptLong::REQUIRED_ARGUMENT],
		['--no-proxy', '-P', GetoptLong::NO_ARGUMENT],
		['--delete-after', '-d', GetoptLong::NO_ARGUMENT],
		['--force-update', '-f', GetoptLong::NO_ARGUMENT],
		['--check-update', '-c', GetoptLong::NO_ARGUMENT],
		['--quiet', '-q', GetoptLong::NO_ARGUMENT],
		['--help', '-h', GetoptLong::NO_ARGUMENT]
# not implemented yet
		#				['--create-symlink', '-c', GetoptLong::NO_ARGUMENT],
		#				['--remove-symlink', '-r', GetoptLong::NO_ARGUMENT],
		)

uninstall = false
help = false
f = UpdateFlashPlugin::FlashUpdater.new()

begin
  opt.each_option { |name, arg|
    f.del = true if name == "--delete-after"
    if name == "--local-file"
      f.local = true
      f.dir = arg
    end
    f.force = true if name == "--force-update"
    f.quiet = true if name == "--quiet"
    f.proxy = arg if name == "--proxy"
    f.no_proxy = true if name == "--no-proxy"
    uninstall = true if name == "--uninstall"
    help = true  if name == "--help"
    f.check_only = true if name == "--check-update"
  }
rescue
  exit
end

if help
  print <<EOF
usage: update-flashplugin [options]
options:
	--uninstall, -u                 --  uninstall
	--local-file, -l <directory>    --  use local file 
	--proxy, -p <http_proxy>        --  use specified proxy
	--no-proxy, -P                  --  don't use proxy
	--delete-after, -d              --  delete archive after install
	--force-update, -f              --  force update
	--check-update, -c              --  only check new version
	--quiet, -q                     --  be quiet
	--help, -h                      --  print this

see also update-flashplugin(8)
EOF
  exit
end

if uninstall
  f.uninstall
  exit
end

f.check_installed
host = f.check_update

if ( f.force || f.need_update ) && ! f.check_only
  f.update( host )
  if File.exist?("/usr/sbin/update-mozilla-chrome")
    system("/usr/sbin/update-mozilla-chrome")
  end
  if File.exist?("/usr/sbin/update-mozilla-snapshot-chrome")
    system("/usr/sbin/update-mozilla-snapshot-chrome")
  end
  if File.exist?("/usr/sbin/update-mozilla-firebird-chrome")
    system("/usr/sbin/update-mozilla-firebird-chrome")
  end
  if File.exist?("/usr/sbin/update-mozilla-firefox-chrome")
    system("/usr/sbin/update-mozilla-firefox-chrome")
  end
end
