129 lines
5.1 KiB
Bash
129 lines
5.1 KiB
Bash
#!/usr/bin/env bash
|
|
# SPDX-License-Identifier: GPL-3.0-or-later
|
|
# Copyright (c) 2025 LUXIM d.o.o., Slovenia
|
|
# Author: Matjaž Mozetič
|
|
#
|
|
# Name: backtunnel-share-gui
|
|
# Summary: KDE/GUI wrapper to start a BackTunnel share with dialogs and logging.
|
|
# Description:
|
|
# GUI front-end that prompts for remote, duration, ports, and invite options using kdialog,
|
|
# then launches backtunnel-share in a terminal (Konsole/xterm) to create the reverse-SSH share.
|
|
# Prefills fields from BackTunnel profiles.ini when available (read-only, best-effort).
|
|
# All output is logged to /tmp/backtunnel-share-gui.<uid>.log for troubleshooting.
|
|
#
|
|
# Usage:
|
|
# backtunnel-share-gui <folder>
|
|
#
|
|
# Examples:
|
|
# backtunnel-share-gui ~/projects
|
|
#
|
|
# Dependencies:
|
|
# - bash
|
|
# - kdialog (for GUI prompts)
|
|
# - konsole or xterm (preferred terminals; falls back to background run if missing)
|
|
# - awk (for simple INI parsing), tee
|
|
# - backtunnel-share (invoked to perform the actual sharing)
|
|
#
|
|
# Exit codes:
|
|
# 0 command launched (terminal or background)
|
|
# 1 invalid usage or no folder selected
|
|
#
|
|
# Notes:
|
|
# - Profiles are used only to prefill fields; @profile is not used directly by this GUI.
|
|
# - If no terminal emulator is available, runs in background and shows a message with the log path.
|
|
|
|
# GUI wrapper for BackTunnel "Share" action (Dolphin service menu)
|
|
# Prompts for parameters via kdialog and launches backtunnel-share in a terminal.
|
|
|
|
set -euo pipefail
|
|
|
|
LOG="/tmp/backtunnel-share-gui.$UID.log"
|
|
exec > >(tee -a "$LOG") 2>&1
|
|
export PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:${PATH:-}"
|
|
|
|
FOLDER="${1:-}"
|
|
if [[ -z "$FOLDER" ]]; then
|
|
kdialog --error "No folder selected." || true
|
|
echo "No folder argument passed from service menu." >>"$LOG"
|
|
exit 1
|
|
fi
|
|
|
|
# Defaults
|
|
REMOTE_DEFAULT="user@vps.example.com"
|
|
DURATION_DEFAULT="2h"
|
|
TPORT_DEFAULT="2222"
|
|
LPORT_DEFAULT="22"
|
|
INVITE_MOUNT_DEFAULT="$HOME/remote-rssh"
|
|
|
|
# Profiles (search order: user -> system -> packaged fallback)
|
|
PROFILES_USER="${XDG_CONFIG_HOME:-$HOME/.config}/backtunnel/profiles.ini"
|
|
PROFILES_SYS="/etc/backtunnel/profiles.ini"
|
|
PROFILES_PKG="/usr/share/backtunnel/profiles.ini"
|
|
if [[ -f "$PROFILES_USER" ]]; then PROFILES_FILE="$PROFILES_USER"
|
|
elif [[ -f "$PROFILES_SYS" ]]; then PROFILES_FILE="$PROFILES_SYS"
|
|
else PROFILES_FILE="$PROFILES_PKG"
|
|
fi
|
|
|
|
# If profiles exist, offer a profile picker and prefill dialogs
|
|
if [[ -f "$PROFILES_FILE" ]]; then
|
|
mapfile -t profs < <(awk '/^\[/{gsub(/^\[|\]$/,"",$1); if ($1!="default") print $1}' "$PROFILES_FILE")
|
|
if (( ${#profs[@]} )); then
|
|
choice="$(kdialog --combobox "Choose profile (or Cancel for manual)" "${profs[@]}")" || choice=""
|
|
if [[ -n "$choice" ]]; then
|
|
getval() { awk -v s="[""$choice""]" -v k="$1" '
|
|
$0==s{ok=1; next} /^\[/{ok=0}
|
|
ok && $0 ~ /^[[:alnum:]_.-]+[[:space:]]*=/ {
|
|
line=$0; sub(/[[:space:]]*=[[:space:]]*/, "=", line)
|
|
split(line,a,"="); if(a[1]==k){val=substr(line,index(line,"=")+1); gsub(/^[[:space:]]+|[[:space:]]+$/,"",val); print val; exit}
|
|
}' "$PROFILES_FILE" 2>/dev/null; }
|
|
u="$(getval user)"; h="$(getval host)"
|
|
if [[ -n "$u" && -n "$h" ]]; then
|
|
REMOTE_DEFAULT="$u@$h"
|
|
fi
|
|
v="$(getval tunnel_port)"; [[ -n "$v" ]] && TPORT_DEFAULT="$v"
|
|
v="$(getval local_ssh_port)"; [[ -n "$v" ]] && LPORT_DEFAULT="$v"
|
|
v="$(getval invite_mount)"; [[ -n "$v" ]] && INVITE_MOUNT_DEFAULT="$v"
|
|
# optional: default duration from [default]
|
|
vd="$(awk -v s="[default]" -v k="duration" '
|
|
$0==s{ok=1; next} /^\[/{ok=0}
|
|
ok && $0 ~ /^[[:alnum:]_.-]+[[:space:]]*=/ {
|
|
line=$0; sub(/[[:space:]]*=[[:space:]]*/, "=", line)
|
|
split(line,a,"="); if(a[1]==k){val=substr(line,index(line,"=")+1); gsub(/^[[:space:]]+|[[:space:]]+$/,"",val); print val; exit}
|
|
}' "$PROFILES_FILE" 2>/dev/null)"
|
|
[[ -n "$vd" ]] && DURATION_DEFAULT="$vd"
|
|
fi
|
|
fi
|
|
fi
|
|
|
|
# Dialogs (Cancel returns 1; treat as benign exit)
|
|
REMOTE="$(kdialog --inputbox "Remote (user@host or user:host):" "$REMOTE_DEFAULT")" || exit 0
|
|
DUR="$(kdialog --combobox "Share duration" 30m 2h 6h 1d 2d --editable "$DURATION_DEFAULT")" || exit 0
|
|
TPORT="$(kdialog --inputbox "Tunnel port on remote:" "$TPORT_DEFAULT")" || exit 0
|
|
LPORT="$(kdialog --inputbox "Local SSH port to expose:" "$LPORT_DEFAULT")" || exit 0
|
|
|
|
INV="" # set to "-i" if chosen
|
|
if kdialog --yesno "Print invite line for chat?"; then
|
|
INV="-i"
|
|
fi
|
|
|
|
QR="" # set to "--qr" if chosen
|
|
if kdialog --yesno "Show QR code for the invite?"; then
|
|
QR="--qr"
|
|
fi
|
|
|
|
MP="$(kdialog --inputbox "Suggested mount point in invite:" "$INVITE_MOUNT_DEFAULT")" || exit 0
|
|
|
|
# Build command safely as an array; append optional flags conditionally (SC2206-safe)
|
|
cmd=( backtunnel-share "$FOLDER" with "$REMOTE" for "$DUR" -p "$TPORT" -l "$LPORT" --invite-mount "$MP" )
|
|
if [[ -n "$INV" ]]; then cmd+=("$INV"); fi
|
|
if [[ -n "$QR" ]]; then cmd+=("$QR"); fi
|
|
|
|
if command -v konsole >/dev/null 2>&1; then
|
|
exec konsole --noclose -e "${cmd[@]}"
|
|
elif command -v xterm >/dev/null 2>&1; then
|
|
exec xterm -hold -e "${cmd[@]}"
|
|
else
|
|
nohup "${cmd[@]}" >>"$LOG" 2>&1 &
|
|
kdialog --msgbox "Sharing started in background.\nSee log: $LOG"
|
|
exit 0
|
|
fi |