#!/bin/sh
#
# @packag       hubzero-filexfer
# @file	        exportfile
# @author       Michael McLennan <mmclennan@purdue.edu>
# @author       Derrick Kearney <dsk@purdue.edu>
# @author	Nicholas J. Kisseberth <nkissebe@purdue.edu>
# @copyright    Copyright (c) 2004-2013 HUBzero Foundation, LLC.
# @license      http://www.gnu.org/licenses/lgpl-3.0.html LGPLv3
#
# Copyright (c) 2004-2013 HUBzero Foundation, LLC.
#
# This file is part of: The HUBzero(R) Platform for Scientific Collaboration
#
# The HUBzero(R) Platform for Scientific Collaboration (HUBzero) is free
# software: you can redistribute it and/or modify it under the terms of
# the GNU Lesser General Public License as published by the Free Software
# Foundation, either version 3 of the License, or (at your option) any
# later version.
#
# HUBzero is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.
#
# HUBzero is a registered trademark of HUBzero Foundation, LLC.
#

# ----------------------------------------------------------------------
#  USAGE: exportfile ?options? file file ...
#
#    options:
#      -h or --help
#        Prints a help message.
#
#      -t or --timeout <seconds>
#        Forget about the file after this timeout.  Default is 300
#        seconds (5 minutes).
#
#      -d or --delete
#        Delete the file after the timeout or when the server is shut
#        down.
#
#      -m or --message
#        File containing a fragment of HTML text that will be displayed
#        above the download.  It might say "Here is your data," or
#        "If you use this data, please cite this source."
#
#      -f or --format <type>
#        Choices are "raw" and "html".  Default is "raw".  The "html"
#        format causes the server to rewrite links embedded within
#        the HTML, so that images can be displayed and links can be
#        traversed properly.
#
#      --
#        Remaining arguments are treated as file names, even if they
#        start with a -.
#
#  This is the client that users invoke to transfer files from their
#  session to their desktop.  The client tries to connect to a server
#  to handle the transfer.  If necessary, the client tries to spawn
#  the server and then connect to it.  The server uses the "clientaction"
#  program to open a web page on the client's desktop to download the
#  file.
#
#  Note that the file can be any file in the user's home directory,
#  and therefore is not deleted unless specifically instructed to do
#  so via the --delete option.

# ----------------------------------------------------------------------
#\
. /etc/environ.sh
#\
use -e -r rappture
#\
exec tclsh "$0" ${1+"$@"}
# ----------------------------------------------------------------------
# tclsh executes everything from here on...

# load util procedures from this path
lappend auto_path /usr/share/hubzero-filexfer

array set options {
  --timeout  300
  --delete   0
  --message  ""
  --format   "raw"
}
set usage "$argv0 \[-t|--timeout secs\] \[-d|--delete\] \[-m|--message file\] \[-f|--format raw|html\] file file..."
set manpage "
USAGE: $usage

  options:
    -h or --help
      Prints this help message.

    -t or --timeout <seconds>
      Forget about the file after this timeout.  Default is 86,400
      seconds (1 day).

    -d or --delete
      Delete the file after the timeout or when the tool is shut
      down.  Should be used only with temporary files.

     -m or --message
       File containing a fragment of HTML text that will be displayed
       above the download.  It might say \"Here is your data,\" or
       \"If you use this data, please cite this source.\"

     -f or --format <type>
       Choices are \"raw\" and \"html\".  Default is \"raw\".  The \"html\"
       format causes the server to rewrite links embedded within
       the HTML, so that images can be displayed and links can be
       traversed properly.

    --
      Remaining arguments are treated as file names, even if they
      start with a -.

You can use this command to transfer one or more files from your
tool session to your desktop via a web browser.  A separate web
browser page is opened for each file.  You must have popups enabled
for this to work properly."

#
# Parse all command-line arguments and build up a list of files:
#   file1 timeout1 delete1  file2 timeout2 delete2 ...
#
set xferlist ""

while {[llength $argv] > 0} {
    set opt [lindex $argv 0]
    set argv [lrange $argv 1 end]

    if {"-" != [string index $opt 0]} {
        if {![file exists $opt]} {
            puts stderr "file not found: $opt"
            exit 1
        }
        lappend xferlist $opt $options(--timeout) $options(--delete) $options(--format)
        continue
    }

    switch -- $opt {
        -t - --timeout {
            if {[llength $argv] == 0} {
                puts stderr "missing timeout value for $opt"
                exit 1
            }
            set t [lindex $argv 0]
            set argv [lrange $argv 1 end]
            if {![string is integer $t]} {
                puts stderr "bad timeout value \"$t\": should be integer (seconds)"
                exit 1
            }
            set options(--timeout) $t
        }
        -d - --delete {
            set options(--delete) 1
        }
        -m - --message {
            if {[llength $argv] == 0} {
                puts stderr "missing file name for $opt"
                exit 1
            }
            set m [lindex $argv 0]
            set argv [lrange $argv 1 end]
            if {![file readable $m]} {
                puts stderr "can't read message file \"$m\""
                exit 1
            }
            set options(--message) $m
        }
        -f - --format {
            if {[llength $argv] == 0} {
                puts stderr "missing value for $opt"
                exit 1
            }
            set f [lindex $argv 0]
            set argv [lrange $argv 1 end]
            set choices {raw html}
            if {[lsearch $choices $f] < 0} {
                puts stderr "bad value \"$f\": should be [join $choices {, }]"
                exit 1
            }
            set options(--format) $f
        }
        -h - --help {
            puts $manpage
            exit
        }
        -- {
            foreach file $argv {
                if {![file exists $file]} {
                    puts stderr "file not found: $file"
                    exit 1
                } elseif {[file isdirectory $file]} {
                    puts stderr "cannot export directory: $file, use 'tar' to create file."
                    exit 1
                }
                lappend xferlist $file $options(--timeout) $options(--delete) $options(--format)
            }
            set argv ""
        }
        default {
            puts stderr "bad option \"$opt\""
            puts stderr $usage
            exit 1
        }
    }
}

#
# Load the settings from the user's resources file.
# In particular, figure out filexfer_port so we know how to talk
# to the filexfer server.
#
if {[catch {filexfer::resources} result]} {
    puts stderr "can't load resource configuration:"
    puts stderr $result
    exit 1
}
array set settings $result

if {![info exists settings(port)]} {
    puts stderr "missing filexfer_port in resource settings"
    exit 1
}
if {![info exists settings(cookie)]} {
    puts stderr "missing filexfer_cookie in resource settings"
    exit 1
}

#
# Make a connection to the filexfer server.  Spawn the server, if
# necessary.
#
set buffer ""
proc server_mesg {sid} {
    global finished buffer

    if {[gets $sid line] < 0} {
        set finished 1
    } else {
        append buffer $line "\n"
        if {[info complete $buffer]} {
            set cmd $buffer
            set buffer ""
            set word [lindex $cmd 0]
            switch -- $word {
              ERROR {
                set mesg [lindex $cmd 1]
                puts stderr $mesg
                exit 1
              }
              default {
                puts "HUH? $cmd"
              }
            }
        }
    }
}

set message ""
if {[string length $options(--message)] > 0} {
    set cmds {
        set fid [open $options(--message) r]
        set message [read $fid]
        close $fid
        # strip out newlines, which message up protocol sent below
        regsub -all {[\r\n]} $message " " message
    }
    if {[catch $cmds result]} {
        puts stderr "can't load messaage file \"$options(--message)\":"
        puts stderr $result
        exit 1
    }
}

if {[llength $xferlist] > 0} {
    if {[catch {filexfer::connect $settings(port) server_mesg} sid]} {
        puts stderr "can't connect to filexfer server: $sid"
        exit 1
    }

    set hubname "???"
    if {[info exists settings(hubname)]} {
        set hubname $settings(hubname)
    }

    set csspath "tools/assets/css"
    if {[info exists settings(hubtemplate)]} {
        set csspath "templates/$settings(hubtemplate)/css"
    }

    set subs [list \
        @HUBNAME@ $hubname \
        @CSSPATH@ $csspath \
        @MESSAGE@ $message \
    ]

    foreach {file timeout delete format} $xferlist {
        if {[file pathtype $file] == "relative"} {
            set file [file join [pwd] $file]
        }
        puts $sid [list EXPORT $file $timeout $delete $format $subs $settings(cookie) FILEXFER/1.1]
    }
    puts $sid "BYE $settings(cookie) FILEXFER/1.1"

    vwait finished  ;# wait for server to close
}
