diff --git a/tools/system/copy_firefox_extension.sh b/tools/system/copy_firefox_extension.sh index e6777d0..87815e0 100755 --- a/tools/system/copy_firefox_extension.sh +++ b/tools/system/copy_firefox_extension.sh @@ -2,13 +2,43 @@ set -euo pipefail -EXTENSION_NAME="${1:-bitwarden}" -DIRECTION="${2:-inet-to-intra}" +usage() { + echo "Usage: $0 [extension_name|all] [inet-to-intra|intra-to-inet]" + echo " no arguments: list extension names from the source profile" + echo " extension_name: copy the first matching extension by name" + echo " all: copy every extension from source to target" + echo " direction: which way to copy (default: inet-to-intra)" +} + +EXTENSION_NAME="" +DIRECTION="inet-to-intra" + +case $# in + 0) + ;; + 1) + case "$1" in + inet-to-intra|intra-to-inet) + usage + exit 1 + ;; + *) + EXTENSION_NAME="$1" + ;; + esac + ;; + 2) + EXTENSION_NAME="$1" + DIRECTION="$2" + ;; + *) + usage + exit 1 + ;; +esac if [[ "$DIRECTION" != "inet-to-intra" && "$DIRECTION" != "intra-to-inet" ]]; then - echo "Usage: $0 [extension_name] [inet-to-intra|intra-to-inet]" - echo " extension_name: Name to search for (default: bitwarden)" - echo " direction: Which way to copy (default: inet-to-intra)" + usage exit 1 fi @@ -29,7 +59,7 @@ find_base_path() { find_profile() { local base="$1" local name="$2" - + local pattern case "$name" in internet) @@ -41,7 +71,7 @@ find_profile() { *) pattern="*${name}*" ;; esac - + for prof in "$base"/$pattern; do if [[ -d "$prof" ]]; then echo "$prof" @@ -53,11 +83,11 @@ find_profile() { list_profiles() { local base="$1" - + if [[ ! -d "$base" ]]; then return 1 fi - + for prof in "$base"/*.default*; do if [[ -d "$prof" ]]; then echo "$prof" @@ -73,11 +103,11 @@ list_profiles() { find_extension() { local ext_dir="$1" local name="$2" - + if [[ ! -d "$ext_dir" ]]; then return 1 fi - + for ext in "$ext_dir"/*; do if [[ -d "$ext" ]]; then if [[ -f "$ext/manifest.json" ]]; then @@ -93,27 +123,93 @@ find_extension() { fi fi done - + return 1 } +list_extensions() { + local ext_dir="$1" + + if [[ ! -d "$ext_dir" ]]; then + return 1 + fi + + shopt -s nullglob + for ext in "$ext_dir"/*; do + if [[ -d "$ext" ]]; then + if [[ -f "$ext/manifest.json" ]]; then + local manifest_name + manifest_name=$(grep -oE '"name"[[:space:]]*:[[:space:]]*"[^"]+"' "$ext/manifest.json" 2>/dev/null | head -n1 | sed -E 's/.*"([^"]+)".*/\1/' || true) + if [[ -n "$manifest_name" ]]; then + echo "$manifest_name" + else + echo "$(basename "$ext")" + fi + fi + elif [[ -f "$ext" ]] && [[ "$ext" == *.xpi ]]; then + local manifest_name + manifest_name=$(unzip -p "$ext" manifest.json 2>/dev/null | grep -oE '"name"[[:space:]]*:[[:space:]]*"[^"]+"' | head -n1 | sed -E 's/.*"([^"]+)".*/\1/' || true) + if [[ -n "$manifest_name" ]]; then + echo "$manifest_name" + else + echo "$(basename "$ext")" + fi + fi + done + shopt -u nullglob +} + +copy_all_extensions() { + local source_ext_dir="$1" + local target_ext_dir="$2" + + if [[ ! -d "$source_ext_dir" ]]; then + echo "Error: Source extensions directory not found" + exit 1 + fi + + mkdir -p "$target_ext_dir" + + shopt -s nullglob + local copied=0 + for ext in "$source_ext_dir"/*; do + local ext_name + ext_name=$(basename "$ext") + local target_ext="$target_ext_dir/$ext_name" + + if [[ -e "$target_ext" ]]; then + echo "Removing existing extension from target: $ext_name" + rm -rf "$target_ext" + fi + + cp -r "$ext" "$target_ext" + echo "Copied: $ext_name" + copied=1 + done + shopt -u nullglob + + if [[ $copied -eq 0 ]]; then + echo "No extensions found to copy." + fi +} + main() { echo "=== Firefox Extension Sync ($DIRECTION) ===" echo "" - + local base_path base_path=$(find_base_path) || { echo "Error: Could not find Firefox profile directory" exit 1 } - + echo "Profile base path: $base_path" echo "Available profiles:" list_profiles "$base_path" | while read -r p; do echo " - $(basename "$p")" done echo "" - + local source_profile target_profile case "$DIRECTION" in inet-to-intra) @@ -125,45 +221,66 @@ main() { target_profile=$(find_profile "$base_path" "internet") ;; esac - + if [[ -z "$source_profile" ]]; then echo "Error: Could not find source profile" exit 1 fi - + if [[ -z "$target_profile" ]]; then echo "Error: Could not find target profile" exit 1 fi - + echo "Source: $(basename "$source_profile")" echo "Target: $(basename "$target_profile")" echo "" - + + if [[ -z "$EXTENSION_NAME" ]]; then + echo "Extensions in source profile:" + local found=0 + while IFS= read -r ext; do + found=1 + [[ -n "$ext" ]] && echo " - $ext" + done < <(list_extensions "$source_profile/extensions" || true) + if [[ $found -eq 0 ]]; then + echo " - " + fi + exit 0 + fi + + if [[ "$EXTENSION_NAME" == "all" ]]; then + echo "Copying all extensions..." + copy_all_extensions "$source_profile/extensions" "$target_profile/extensions" + echo "" + echo "Done! Restart Firefox to load the extensions." + exit 0 + fi + local source_ext source_ext=$(find_extension "$source_profile/extensions" "$EXTENSION_NAME") || { echo "Error: $EXTENSION_NAME extension not found in source profile" exit 1 } - + local ext_name ext_name=$(basename "$source_ext") - + echo "Found extension: $ext_name" echo "" - + local target_ext="$target_profile/extensions/$ext_name" - + if [[ -d "$target_ext" ]]; then echo "Removing existing extension from target..." rm -rf "$target_ext" fi - + cp -r "$source_ext" "$target_ext" - + echo "Copied successfully!" echo "" echo "Done! Restart Firefox to load the extension." } -main "$@" \ No newline at end of file +main "$@"