#!/bin/bash if [ -f ~/.shcrtrc ]; then source ~/.shcrtrc else cat > ~/.shcrtrc << EOF ## GUI mode # # Console based: # dialog - ncurses, runs fine on WSL # none - works everywhere # # GUI based: # yad, gtkdialog, kdialog, Xdialog - GNU/Linux only # zenity - Windows port available, doesn't work very well because Microsoft is a little bitch and # argument passing between Linux and Windows doesn't work well. #export supermode="zenity" ## Emojis - auto, yes, no #export emojis="auto" ## Custom SecureCRT config path # Set to override defaults: # - GNU/Linux: ~/.vandyke/SecureCRT/Config # - Windows: %APPDATA%/VanDyke/Config # On WSL it needs to be a Linux path! #export crtconfig="/your/path/to/Config" ## Session default action # You can define the action that will be run when you select a session # file. Default is "ask" # - ask # - print # - exec_ssh # - exec_sftp #export default_action="ask" ## SFTP runner # To run a SFTP program, you need to specify an helper command. # It needs to accept an SSH-like command: # sftp_client_runner user@host -p port # # A FileZilla runner is provided and it should work on GNU/Linux and WSL #export sftp_client_runner=run_filezilla EOF fi function is_wsl { grep -q Microsoft /proc/version return $? } if is_wsl; then function zenity { zenity.exe "$@" | tr -d '\r' } fi # Determine script location SOURCE="${BASH_SOURCE[0]}" while [ -h "$SOURCE" ]; do # resolve $SOURCE until the file is no longer a symlink DIR="$( cd -P "$( dirname "$SOURCE" )" >/dev/null 2>&1 && pwd )" SOURCE="$(readlink "$SOURCE")" # if $SOURCE was a relative symlink, we need to resolve it relative to the path where the symlink file was located [[ $SOURCE != /* ]] && SOURCE="$DIR/$SOURCE" done DIR="$( cd -P "$( dirname "$SOURCE" )" >/dev/null 2>&1 && pwd )" export supertitle="shcrt" export SHELL_LIBRARY_PATH="$SHELL_LIBRARY_PATH:$DIR/easybashgui/lib" export PATH="$PATH:$DIR/easybashgui/src" source easybashgui source "$DIR/sftp_runners.sh" function wsl_win_var { cmd.exe /C "echo $1" | tr -d '\r' } function win_path_to_wsl { if [[ "$1" != "" ]]; then echo "$1" | sed -e 's|\\|/|g' -e 's|\(.*\):|/mnt/\L\1|' else cat - | sed -e 's|\\|/|g' -e 's|\(.*\):|/mnt/\L\1|' fi } function copy_to_clipboard { if is_wsl; then cat - | clip.exe elif [[ "$WAYLAND_DISPLAY" != "" ]] && which wl-copy > /dev/null; then cat - | wl-copy elif which xclip > /dev/null; then cat - | xclip -selection clipboard else return 1 fi } # Escape bash variables function no_dollars { sed 's/\$/\\$/g' } function scrt_session_path { if [[ "$crtconfig" != "" ]]; then echo "$crtconfig/Sessions" else if is_wsl; then appdata="$(wsl_win_var '%APPDATA%' | win_path_to_wsl)" echo "$appdata/VanDyke/Config/Sessions" else echo "$HOME/.vandyke/SecureCRT/Config/Sessions" fi fi } if [[ "$emojis" == "no" ]] || ([[ "$emojis" != "yes" ]] && is_wsl); then dir_char="+" file_char=" " search_entry="> Search" up_entry=".. Back" exit_search_entry="X Exit search" query_question="Enter search query: " now_at_entry="Now at: " else dir_char="📁" file_char="🔗" search_entry="🔍 Search" up_entry="↩ī¸ .. Back" exit_search_entry="❌ Exit search" query_question="🔍 Enter search query: " now_at_entry="📍 Now at: " fi run_ssh_entry="Run SSH" run_sftp_entry="Run SFTP client" print_details_entry="Print details and exit" session_path="$(scrt_session_path)" current_path="." function scrt_cd { newdir="$session_path/$current_path/$1" if [ ! -d "$newdir" ]; then return 1 fi current_path="$(realpath --no-symlinks --relative-to "$session_path" "$newdir")" } function scrt_pwd { echo "$session_path/$current_path" } function find_dirs_or_symlinks { while read -r name; do [ -d "$name" ] && echo "$name"; done < <(find $@) } function find_files_or_symlinks { while read -r name; do [ -f "$name" ] && echo "$name"; done < <(find $@) } function scrt_session_name { local file="$1" proto="$(cat "$file" | grep 'S:"Protocol Name"' | cut -d '=' -f 2 | tr -d '\r')" echo "$file_char $(echo "$(basename "$file")" | sed 's/.ini$//') ($proto)" } function scrt_ls { cwd="$(pwd)" cd "$(scrt_pwd)" find_dirs_or_symlinks -maxdepth 1 -mindepth 1 | sort | sed "s|./||" | while read dir; do echo "$dir_char $dir\\$dir" done find_files_or_symlinks -maxdepth 1 -mindepth 1 | grep '.ini$' | grep -v 'Default.ini' | grep -v '__FolderData__.ini' | sort | sed 's|./||' | while read file; do echo "$(scrt_session_name "$file")\\$file" done cd "$cwd" } function scrt_find { query="$1" ( find "$session_path/$current_path" -type d -iname '*'"$query"'*' find "$session_path/$current_path" -type f -iname '*'"$query"'*.ini$' | grep -v "__FolderData__.ini" | grep -v "Default.ini" )| while read result; do if basename "$result" | grep -qi "$query"; then realpath --relative-to "$session_path/$current_path" "$result" fi done } function scrt_search { input 1 "$query_question" query="$(cat "${dir_tmp}/${file_tmp}")" query="${query#"$query_question"}" if [[ "$query" == "" ]]; then return 1 fi results="$(scrt_find "$query")" if [[ "$results" == "" ]]; then alert_message "No results" return 1; fi IFSBAK="$IFS" IFS=$'\n' menu "$exit_search_entry" $results IFS="$IFSBAK" menu_choice="$(0< "${dir_tmp}/${file_tmp}" )" if [[ "$menu_choice" == "$exit_search_entry" ]]; then return 1 else choice_path="$(scrt_pwd)/$menu_choice" if [ -d "$choice_path" ]; then scrt_cd "$menu_choice" return 1 else scrt_session_run "$menu_choice" fi fi } function scrt_menu { listing="$(scrt_ls)" menu_listing="$(echo "$listing" | cut -d "\\" -f 1 | no_dollars)" now_at="$(echo "$current_path" | sed -e 's|^[.]|/|' -e 's|//|/|' | no_dollars)" IFSBAK="$IFS" IFS=$'\n' if [[ "$current_path" != "" ]] && [[ "$current_path" != "." ]]; then menu "$now_at_entry $now_at" "$search_entry" "$up_entry" "$menu_listing" else menu "$now_at_entry $now_at" "$search_entry" "$menu_listing" fi IFS="$IFSBAK" menu_choice="$(0< "${dir_tmp}/${file_tmp}" )" choice="$(echo "$listing" | grep "$menu_choice" | cut -d "\\" -f 2)" choice_path="$(scrt_pwd)/$choice" if [[ "$menu_choice" == "" ]] || [[ "$menu_choice" == "$up_entry" ]]; then scrt_cd .. if [[ "$current_path" == "" ]] || [[ "$current_path" == ".." ]]; then return fi elif [[ "$menu_choice" == "$search_entry" ]]; then if scrt_search; then return fi elif [[ "$menu_choice" == "$now_at_entry"* ]]; then scrt_menu elif [ -d "$choice_path" ]; then scrt_cd "$choice" elif [ -f "$choice_path" ]; then scrt_session_run "$choice_path" else alert_message "Could not find selected item \"$menu_choice\"" fi scrt_menu } function scrt_has_password { cat "$1" | grep -q '"Password"' return $? } function scrt_get_cleartext_pwd { session="$1" encrypted="$(cat "$session" | grep '"Password V2"' | cut -d '=' -f 2 | cut -c 1-3 --complement | tr -d '\r')" if [[ "$encrypted" == "" ]]; then encrypted="$(cat "$session" | grep '"Password"' | cut -d '=' -f 2 | cut -c 1 --complement | tr -d '\r')" "$DIR/SecureCRTCipher.py" dec "$encrypted" else "$DIR/SecureCRTCipher.py" dec -v2 "$encrypted" fi } function scrt_session_run { local session="$1" if [[ "$default_action" == run* ]]; then # No stack overflows, bitch default_action="ask" fi (type "scrt_session_$default_action") 2>&1 >/dev/null && \ "scrt_session_$default_action" "$session" || \ scrt_session_ask "$@" } function scrt_session_ask { local session="$1" local file="$(realpath --no-symlinks "$session")" menu \ "$run_ssh_entry" \ "$run_sftp_entry" \ "$print_details_entry" \ "------" \ "Session: $(scrt_session_name "$session")" menu_choice="$(0< "${dir_tmp}/${file_tmp}" )" case "$menu_choice" in "$run_ssh_entry") scrt_session_exec_ssh "$file" ;; "$run_sftp_entry") scrt_session_exec_sftp "$file" ;; "$print_details_entry") scrt_session_print "$session" ;; "") return ;; esac scrt_session_ask "$session" } function scrt_session_exec_ssh { local session="$1" scrt_session_copy_pass "$session" echo cmd="$("$DIR/crt2foss.py" "$session_path/../" "$session" | grep '^ssh')" echo "\$ $cmd" exec $cmd } function scrt_session_exec_sftp { local session="$1" (type "sftp_client_runner") 2>&1 >/dev/null if [[ "$?" != 0 ]]; then alert_message "You need to provide an SFTP client helper.\n\nYou can either provide it as a function named\n'sftp_client_runner' in ~/.shcrtrc or place it in \$PATH" return 1 fi scrt_session_copy_pass "$session" echo cmd="$("$DIR/crt2foss.py" "$session_path/../" "$session" | grep '^ssh' | sed 's/^ssh/sftp_client_runner/')" $cmd exit } function scrt_session_copy_pass { local session="$1" if scrt_has_password "$session"; then echo if scrt_get_cleartext_pwd "$session" 2> /dev/null | tr -d '\r\n' | copy_to_clipboard; then echo "Password copied to clipboard." else echo "Unable to copy password to clipboard." read -p "Do you want me to print it to the console? [yN] " yn case $yn in [Yy]*) scrt_get_cleartext_pwd "$session";; esac fi fi } function scrt_session_print { if [[ "$mode" == "dialog" ]] || [[ "$supermode" == "dialog" ]]; then clear fi local session="$1" echo echo "Session file:" realpath --no-symlinks "$session" echo echo "Commands:" "$DIR/crt2foss.py" "$session_path/../" "$session" scrt_session_copy_pass "$session" exit } function main { if [ ! -d "$session_path" ]; then alert_message "SecureCRT session path not found.\nLooked for it at:\n$session_path" return 1 fi scrt_menu } # Run if not sourced BASH_SOURCE=".$0" test ".$0" != ".$BASH_SOURCE" || main $@