| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326 | #!/usr/bin/env tclsh## Copyright (c) 2015-2017 OpenIndex.de## Permission is hereby granted, free of charge, to any person obtaining a copy# of this software and associated documentation files (the "Software"), to deal# in the Software without restriction, including without limitation the rights# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell# copies of the Software, and to permit persons to whom the Software is# furnished to do so, subject to the following conditions:## The above copyright notice and this permission notice shall be included in# all copies or substantial portions of the Software.## THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN# THE SOFTWARE.#package require Tkpackage require msgcatnamespace eval ::support {  variable TITLE  variable VERSION  variable ICON  variable WRAPPED  variable APP_DIR  variable DATA_DIR  variable TEMP_DIR  variable LOG_NAME  variable MAC_APPLICATION_BUNDLE 0  variable FRAME  variable CONNECTED 0  # Launch application.  proc launch {dir wrapped version} {    global env    global tcl_platform    variable MAC_APPLICATION_BUNDLE    # Get application base path.    if {$wrapped && [info exists env(MAC_APPLICATION_BUNDLE)]} {      variable APP_DIR [file dirname [file dirname [file dirname [file dirname $dir]]]]      variable LOG_NAME [file tail [file dirname [file dirname [file dirname $dir]]]]      set MAC_APPLICATION_BUNDLE 1      set pos [string last "." $LOG_NAME]      if {$pos > 0} {        set LOG_NAME [string range $LOG_NAME 0 [expr {$pos-1}]]      }    } elseif {$wrapped} {      variable APP_DIR [file dirname $dir]      variable LOG_NAME [file tail $dir]      # Remove exe file extension from log name on Windows.      if {[::support::utils::is_windows]} {        set pos [string last "." $LOG_NAME]        if {$pos > 0} {          set LOG_NAME [string range $LOG_NAME 0 [expr {$pos-1}]]        }      }    } else {      variable APP_DIR $dir      variable LOG_NAME "support"    }    # Init logging.    set ::support::logger::FILE [file join $APP_DIR [format "%s.log" $LOG_NAME]]    fconfigure stdout -buffering line    fconfigure stderr -buffering line    chan push stdout ::support::logger    chan push stderr ::support::logger    # Init translations.    ::msgcat::mcload [file join $dir "lib" "app-support" "msgs"]    # Set application settings.    variable TITLE [_ "Remote Support Tool"]    variable VERSION $version    variable WRAPPED $wrapped    variable DATA_DIR [file join $dir "data"]    # Detect temporary directory.    variable TEMP_DIR [file join [::support::utils::get_temp_dir] "temp-support-[pid]"]    if {![file exists $TEMP_DIR]} {      if {[catch {file mkdir $TEMP_DIR}]} {        puts "ERROR: The temporary directory \"$TEMP_DIR\" was not created!"      }    } elseif {![file isdirectory $TEMP_DIR]} {      puts "ERROR: The temporary directory \"$TEMP_DIR\" is not a directory!"    }    # Print some informations.    puts ""    puts "-----------------------------------------------------------------------------"    puts " $TITLE $VERSION"    puts "-----------------------------------------------------------------------------"    puts " system         : $tcl_platform(os) $tcl_platform(osVersion)"    puts " machine        : $tcl_platform(machine) / $tcl_platform(platform)"    puts " host name      : [info hostname]"    puts " user name      : $tcl_platform(user)"    puts " user home      : $env(HOME)"    puts " tcl version    : [info patchlevel]"    if {[info exists tcl_platform(threaded)]} {      puts " tcl threads    : enabled"    } else {      puts " tcl threads    : disabled"    }    puts " tcl executable : [info nameofexecutable]"    puts " root directory : $dir"    puts " work directory : [pwd]"    puts " temp directory : $TEMP_DIR"    puts "-----------------------------------------------------------------------------"    puts "THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR"    puts "IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,"    puts "FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE"    puts "AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER"    puts "LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,"    puts "OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN"    puts "THE SOFTWARE."    puts "-----------------------------------------------------------------------------"    #parray env    #puts "-----------------------------------------------------------------------------"    # Load global configuration.    set cfgFile [file join $DATA_DIR config_global.ini]    if {$cfgFile != "" && [file isfile $cfgFile]} {      ::support::Config::configure $cfgFile    }    # Load custom configuration.    set cfgFile [file join $DATA_DIR config.ini]    if {$cfgFile != "" && [file isfile $cfgFile]} {      ::support::Config::configure $cfgFile    }    set cfgFile [file join $APP_DIR config.ini]    if {$cfgFile != "" && [file isfile $cfgFile]} {      puts "Load custom configuration from '$cfgFile'."      ::support::Config::configure $cfgFile    }    # Load application icon.    variable ICON [::support::utils::load_image_file icon.png]    # Initialize VNC session.    ::support::session::init    if {[::support::utils::is_darwin]} {      # Show settings window through the Mac OS X menubar.      proc ::tk::mac::ShowPreferences {} {        ::support::SettingsWindow::open      }      # Show about window through the Mac OS X menubar.      proc ::tkAboutDialog {} {        ::support::AboutWindow::open      }    }    # Create main frame.    ::support::ApplicationWindow::open    # Mac OS X does not put the application window into foreground.    # As long as we find no better solution, the application is put into    # foreground via AppleScript.    if {[::support::utils::is_darwin]} {      set script "tell application \"System Events\"\n \      set frontmost of the first process whose unix id is [pid] to true\n \      end tell"      if { [catch {exec osascript -e $script} result] } {        puts "Can't put application window into foreground!"        puts $::errorInfo      }    }  }  # Shutdown application.  proc shutdown {} {    exit  }  # Shorthand method for translation.  proc translate {s args} {    return [::msgcat::mc $s {*}$args]  }  # Create VNC connection.  proc connect {} {    variable CONNECTED    ::support::ApplicationWindow::setStatusConnecting    # Launch VNC session.    set result [::support::session::start]    if {$result != 1} {      set CONNECTED 0      puts "VNC connection failed!"      ::support::ApplicationWindow::setStatusError      return    }    # Register connection.    set CONNECTED 1    # Check for valid connection after some seconds.    after 5000 ::support::ping 1  }  # Close VNC connection.  proc disconnect {{force 0}} {    variable CONNECTED 0    if {$force == 1} {      ::support::session::stop      ::support::ApplicationWindow::setStatusDisconnected    }  }  # Test, if a VNC session is currently running.  proc ping {{firstPing 0}} {    #puts "PING"    variable CONNECTED    set running 1    if {$running == 1 && $CONNECTED != 1} {      set running 0      #puts "> VNC connection is closed"    }    if {$running == 1 && ![::support::session::is_running]} {      set running 0      #puts "> VNC is not running anymore"    }    if {$running == 1} {      if {$firstPing == 1} {        ::support::ApplicationWindow::setStatusConnected      }      # Again check for valid connection after some seconds.      after 2500 ::support::ping    } else {      ::support::disconnect 1    }  }}# Handler that writes stdout & stderr into a separate file.namespace eval ::support::logger {  variable FILE  variable HANDLE  proc clear {handle} {  }  proc finalize {handle} {    variable HANDLE    close $HANDLE    unset HANDLE  }  proc initialize {handle mode} {    variable FILE    variable HANDLE    if {![info exists HANDLE]} {      set HANDLE [open $FILE w]    }    return {clear finalize initialize flush write}  }  proc flush {handle} {    variable HANDLE    ::flush $HANDLE  }  proc write {handle buffer} {    variable HANDLE    puts -nonewline $HANDLE $buffer    flush $handle    return $buffer  }  namespace export *  namespace ensemble create}# Shorthand method for translations.proc _ {s args} {  return [::support::translate $s {*}$args]}# Override exit method# to do some cleanups before shutdown.rename exit __exitproc exit {} {  puts "Shutdown application. Have a nice day!"  if {$::support::CONNECTED == 1} {    ::support::disconnect 1  }  # Remove temporary files explicitly.  foreach f [::support::utils::get_files $::support::TEMP_DIR] {    if {[file isfile $f] && [catch {file delete -force $f}]} {      puts "WARNING: Can't remove temporary file \"$f\"!"      puts $::errorInfo    }  }  # Remove temporary folder recursively.  if {[catch {file delete -force $::support::TEMP_DIR}]} {    puts "WARNING: Can't cleanup temporary directory \"$::support::TEMP_DIR\"!"    puts $::errorInfo  }  __exit}
 |