#!/usr/bin/env bash # Copyright (C) 2026 Zaher Salman # SPDX-License-Identifier: GPL-3.0-or-later set -euo pipefail project_root="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" web_target="${TRIMSP_WEB_TARGET:-/var/www/html/TRIMSP-NL}" cgi_target="${TRIMSP_CGI_TARGET:-/var/www/cgi-bin/singleTrimSP.cgi}" trimsp_binary="${TRIMSP_BIN_PATH:-/usr/local/bin/trimspNL}" plotly_source="$project_root/node_modules/plotly.js-dist/plotly.js" plotly_cdn="${TRIMSP_PLOTLY_CDN:-https://cdn.jsdelivr.net/npm/plotly.js-dist@1.58.5/plotly.js}" # Staging files created by this script, removed on exit so a CDN download does # not leak into /tmp after an early failure. tmp_files="" trap 'rm -f $tmp_files' EXIT if [[ ! -x "$trimsp_binary" ]]; then printf 'Installed TRIM.SP-NL binary is not executable: %s\n' "$trimsp_binary" >&2 printf 'Install it first or set TRIMSP_BIN_PATH.\n' >&2 exit 1 fi if [[ ! -f "$plotly_source" ]]; then printf 'Plotly browser bundle not found locally: %s\n' "$plotly_source" >&2 printf 'Downloading bundle from CDN instead ...\n' >&2 if ! command -v curl >/dev/null 2>&1; then printf 'curl is required to download the Plotly bundle.\n' >&2 printf 'Install curl, run npm install, or set TRIMSP_PLOTLY_CDN.\n' >&2 exit 1 fi plotly_tmp="$(mktemp)" tmp_files="$tmp_files $plotly_tmp" if ! curl -fsSL "$plotly_cdn" -o "$plotly_tmp"; then printf 'Failed to download Plotly bundle from %s\n' "$plotly_cdn" >&2 printf 'Run npm install before deploying.\n' >&2 exit 1 fi printf 'Downloaded Plotly bundle from %s\n' "$plotly_cdn" plotly_source="$plotly_tmp" fi perl -c "$project_root/singleTrimSP.cgi" >/dev/null # Install only files used by the browser application. Electron-specific code, # package metadata, tests, and Fortran sources stay outside the document root. install -d -m 0755 "$web_target" "$(dirname "$cgi_target")" install -m 0644 \ "$project_root/TrimSP.html" \ "$project_root/quick-start.html" \ "$project_root/TrimSPlib.js" \ "$project_root/TrimSPweb.js" \ "$project_root/myplots.js" \ "$project_root/ZGUI.css" \ "$project_root/plotly.css" \ "$project_root/icon.png" \ "$web_target/" install -m 0644 "$plotly_source" "$web_target/plotly.js" ln -sfn TrimSP.html "$web_target/index.html" # Brand the installed help page with the current release version, matching the # About dialog in the Electron edition. The source keeps a __TRIMSP_VERSION__ # token that renders as "development build" when left unsubstituted; the # installed copy is rewritten with the version from package.json. Idempotent: # an already-branded file contains no token, so re-running matches nothing. if command -v node >/dev/null 2>&1; then version="$(node -p 'require(process.argv[1]).version' "$project_root/package.json")" tmp_qs="$(mktemp)" tmp_files="$tmp_files $tmp_qs" sed "s#__TRIMSP_VERSION__#$version#g" "$web_target/quick-start.html" > "$tmp_qs" install -m 0644 "$tmp_qs" "$web_target/quick-start.html" printf 'Branded %s with TRIMSP-NL version %s\n' "$web_target/quick-start.html" "$version" else printf 'node not found; quick-start.html keeps the source version token\n' fi # Keep the repository CGI generic while embedding the selected installed # binary path in the deployed copy. cgi_stage="$(mktemp)" tmp_files="$tmp_files $cgi_stage" escaped_trimsp_binary="${trimsp_binary//\\/\\\\}" escaped_trimsp_binary="${escaped_trimsp_binary//&/\\&}" escaped_trimsp_binary="${escaped_trimsp_binary//|/\\|}" escaped_trimsp_binary="${escaped_trimsp_binary//\"/\\\"}" sed 's|^my \$trimsp_bin = .*|my $trimsp_bin = "'"$escaped_trimsp_binary"'";|' \ "$project_root/singleTrimSP.cgi" > "$cgi_stage" install -m 0755 "$cgi_stage" "$cgi_target" # The browser assets and the CGI must be readable (and, for the CGI, # executable) by the web server. On the live server the web space is owned by # the apache user; on a developer machine the files may instead be owned by # the deploying user and served straight from a user-owned tree. Determine the # owner to hand the files to, preferring an explicit override, then a real # web-server account, and keeping the current owner when it is already the # deploying user (the common developer-machine case, where the deploying user # simply owns the web space and chowning to a nonexistent apache user would # fail). web_owner="${TRIMSP_WEB_OWNER:-}" web_group="${TRIMSP_WEB_GROUP:-$web_owner}" if [ -z "$web_owner" ]; then # Detect from the target filesystem: if the deployed tree is already owned # by the invoking user, leave ownership untouched. if [ "$(stat -c %u "$web_target")" = "$(id -u)" ]; then web_owner="" web_group="" else # Prefer a real web-server account when one exists. for cand in apache www-data httpd; do if id "$cand" >/dev/null 2>&1; then web_owner="$cand" web_group="$cand" break fi done # With no matching account, fall back to the invoking user (the trees # were written by this deploy, so they are already owned by them). [ -z "$web_owner" ] && web_owner="$(id -un)" && web_group="$(id -gn)" fi fi if [ -n "$web_owner" ]; then chown -R "$web_owner:$web_group" "$web_target/" chown "$web_owner:$web_group" "$cgi_target" chmod -R u+rX "$web_target/" 2>/dev/null || true fi if command -v restorecon >/dev/null 2>&1; then restorecon -RF "$web_target" "$cgi_target" || true fi printf 'Installed TRIMSP-NL web assets in %s\n' "$web_target" printf 'Installed TRIMSP-NL CGI runner at %s\n' "$cgi_target" printf 'Using installed TRIM.SP-NL engine at %s\n' "$trimsp_binary" if [ -n "$web_owner" ]; then printf 'Ownership set to %s:%s\n' "$web_owner" "$web_group" else printf 'Ownership left unchanged (deployed by the owning user)\n' fi printf '\nThe web server must provide:\n' printf ' /cgi-bin/singleTrimSP.cgi -> %s\n' "$cgi_target" printf 'For SELinux deployments, verify CGI execution and write access with:\n' printf ' ausearch -m avc -ts recent\n'