| | #!/bin/bash |
| | |
| | |
| | |
| | |
| | |
| | |
| |
|
| | |
| | set +e |
| |
|
| | |
| | REPORT_TIMESTAMP=$(date +%Y%m%d_%H%M%S) |
| | OUTPUT_FILE="$HOME/Desktop/plugin_diagnostic_$REPORT_TIMESTAMP.txt" |
| |
|
| | |
| | log() { |
| | echo -e "$1" |
| | |
| | echo -e "$1" | sed 's/\x1b\[[0-9;]*m//g' >> "$OUTPUT_FILE" |
| | } |
| |
|
| | |
| | echo "# After Effects Plugin Diagnostic Report" > "$OUTPUT_FILE" |
| | echo "# Generated: $(date)" >> "$OUTPUT_FILE" |
| | echo "" >> "$OUTPUT_FILE" |
| |
|
| | |
| | RED='\033[0;31m' |
| | GREEN='\033[0;32m' |
| | YELLOW='\033[1;33m' |
| | BLUE='\033[0;34m' |
| | NC='\033[0m' |
| |
|
| | |
| | PASS="β
" |
| | FAIL="β" |
| | WARN="β οΈ" |
| | INFO="βΉοΈ" |
| |
|
| | print_header() { |
| | log "" |
| | log "${BLUE}βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ${NC}" |
| | log "${BLUE} $1${NC}" |
| | log "${BLUE}βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ${NC}" |
| | } |
| |
|
| | print_section() { |
| | log "" |
| | log "${YELLOW}ββ $1 ββ${NC}" |
| | } |
| |
|
| | |
| | DEFAULT_PLUGIN="/Library/Application Support/Adobe/Common/Plug-ins/7.0/MediaCore/BSKL/AIColorMatch.plugin" |
| | MEDIACORE_PATH="/Library/Application Support/Adobe/Common/Plug-ins/7.0/MediaCore" |
| |
|
| | |
| | if [ -z "$1" ]; then |
| | if [ -d "$DEFAULT_PLUGIN" ]; then |
| | PLUGIN_PATH="$DEFAULT_PLUGIN" |
| | echo "Using default plugin path: $PLUGIN_PATH" |
| | else |
| | echo -e "${RED}Usage: bash check_plugin.sh /path/to/Plugin.plugin${NC}" |
| | echo "" |
| | echo "Default plugin not found at:" |
| | echo " $DEFAULT_PLUGIN" |
| | echo "" |
| | echo "Please specify plugin path manually." |
| | exit 1 |
| | fi |
| | else |
| | PLUGIN_PATH="$1" |
| | fi |
| |
|
| | |
| | if [ ! -d "$PLUGIN_PATH" ]; then |
| | log "${FAIL} Plugin not found: $PLUGIN_PATH" |
| | exit 1 |
| | fi |
| |
|
| | |
| | PLUGIN_NAME=$(basename "$PLUGIN_PATH" .plugin) |
| |
|
| | print_header "After Effects Plugin Diagnostic Report" |
| | log "" |
| | log "Plugin: ${GREEN}$PLUGIN_NAME${NC}" |
| | log "Path: $PLUGIN_PATH" |
| | log "Date: $(date)" |
| | log "macOS: $(sw_vers -productVersion) ($(sw_vers -buildVersion))" |
| | log "Machine: $(uname -m)" |
| |
|
| | |
| | |
| | |
| | print_section "All Plugins in MediaCore" |
| |
|
| | if [ -d "$MEDIACORE_PATH" ]; then |
| | log "${BLUE}Scanning: $MEDIACORE_PATH${NC}" |
| | log "" |
| |
|
| | |
| | PLUGIN_COUNT=0 |
| | while IFS= read -r plugin_bundle; do |
| | PLUGIN_COUNT=$((PLUGIN_COUNT + 1)) |
| | plugin_name=$(basename "$plugin_bundle" .plugin) |
| | plugin_modified=$(stat -f "%Sm" -t "%Y-%m-%d %H:%M" "$plugin_bundle" 2>/dev/null || echo "unknown") |
| | plugin_size=$(du -sh "$plugin_bundle" 2>/dev/null | cut -f1 || echo "?") |
| | plugin_perms=$(stat -f "%Sp" "$plugin_bundle" 2>/dev/null || echo "?") |
| | plugin_owner=$(stat -f "%Su:%Sg" "$plugin_bundle" 2>/dev/null || echo "?") |
| |
|
| | |
| | binary_path="$plugin_bundle/Contents/MacOS/$plugin_name" |
| | if [ -f "$binary_path" ]; then |
| | arch=$(lipo -archs "$binary_path" 2>/dev/null || echo "?") |
| | binary_perms=$(stat -f "%Sp" "$binary_path" 2>/dev/null || echo "?") |
| |
|
| | |
| | codesign_check=$(codesign -dv --verbose=2 "$plugin_bundle" 2>&1) |
| | if echo "$codesign_check" | grep -q "Authority="; then |
| | signer=$(echo "$codesign_check" | grep "Authority=" | head -1 | cut -d= -f2 | cut -c1-40) |
| | sign_status="$PASS" |
| | elif echo "$codesign_check" | grep -q "Signature=adhoc"; then |
| | signer="ad-hoc" |
| | sign_status="$WARN" |
| | elif echo "$codesign_check" | grep -q "TeamIdentifier="; then |
| | |
| | team=$(echo "$codesign_check" | grep "TeamIdentifier=" | cut -d= -f2) |
| | signer="Team: $team" |
| | sign_status="$PASS" |
| | else |
| | signer="unsigned" |
| | sign_status="$FAIL" |
| | fi |
| |
|
| | |
| | if echo "$codesign_check" | grep -q "Notarization Ticket"; then |
| | notarized="yes" |
| | else |
| | notarized="no" |
| | fi |
| |
|
| | |
| | quarantine_check=$(xattr -p com.apple.quarantine "$plugin_bundle" 2>/dev/null) |
| | if [ -n "$quarantine_check" ]; then |
| | qflag="$WARN quarantined" |
| | else |
| | qflag="" |
| | fi |
| |
|
| | log "$sign_status $plugin_name $qflag" |
| | log " Modified: $plugin_modified | Size: $plugin_size | Arch: $arch" |
| | log " Perms: $plugin_perms | Binary: $binary_perms | Owner: $plugin_owner" |
| | log " Signed: $signer | Notarized: $notarized" |
| | else |
| | log "$WARN $plugin_name (binary missing)" |
| | log " Modified: $plugin_modified | Size: $plugin_size" |
| | log " Perms: $plugin_perms | Owner: $plugin_owner" |
| | fi |
| | log "" |
| | done < <(find "$MEDIACORE_PATH" -maxdepth 2 -name "*.plugin" -type d 2>/dev/null | sort) |
| |
|
| | log "Total plugins found: $PLUGIN_COUNT" |
| | else |
| | log "$WARN MediaCore directory not found: $MEDIACORE_PATH" |
| | fi |
| |
|
| | |
| | |
| | |
| | print_section "Plugin Structure" |
| |
|
| | BINARY_PATH="$PLUGIN_PATH/Contents/MacOS/$PLUGIN_NAME" |
| | PLIST_PATH="$PLUGIN_PATH/Contents/Info.plist" |
| | RSRC_PATH="$PLUGIN_PATH/Contents/Resources/$PLUGIN_NAME.rsrc" |
| |
|
| | if [ -f "$BINARY_PATH" ]; then |
| | log "$PASS Binary: $BINARY_PATH" |
| | BINARY_SIZE=$(du -h "$BINARY_PATH" | cut -f1) |
| | log " Size: $BINARY_SIZE" |
| | else |
| | log "$FAIL Binary NOT FOUND: $BINARY_PATH" |
| | fi |
| |
|
| | if [ -f "$PLIST_PATH" ]; then |
| | log "$PASS Info.plist: exists" |
| | else |
| | log "$FAIL Info.plist NOT FOUND" |
| | fi |
| |
|
| | if [ -f "$RSRC_PATH" ]; then |
| | log "$PASS Resource file: $PLUGIN_NAME.rsrc" |
| | else |
| | log "$WARN Resource file not found (may be embedded)" |
| | fi |
| |
|
| | |
| | |
| | |
| | print_section "Architecture" |
| |
|
| | if [ -f "$BINARY_PATH" ]; then |
| | ARCHS=$(lipo -archs "$BINARY_PATH" 2>/dev/null || echo "unknown") |
| |
|
| | if [[ "$ARCHS" == *"arm64"* ]] && [[ "$ARCHS" == *"x86_64"* ]]; then |
| | log "$PASS Universal Binary: $ARCHS" |
| | elif [[ "$ARCHS" == *"arm64"* ]]; then |
| | log "$WARN ARM64 only (no Intel support)" |
| | elif [[ "$ARCHS" == *"x86_64"* ]]; then |
| | log "$WARN Intel only (no Apple Silicon native)" |
| | else |
| | log "$FAIL Unknown architecture: $ARCHS" |
| | fi |
| |
|
| | |
| | MACHINE_ARCH=$(uname -m) |
| | log "$INFO Current machine: $MACHINE_ARCH" |
| | fi |
| |
|
| | |
| | |
| | |
| | print_section "Dependencies" |
| |
|
| | if [ -f "$BINARY_PATH" ]; then |
| | MISSING_DEPS=0 |
| |
|
| | |
| | while IFS= read -r line; do |
| | |
| | [[ -z "$line" ]] && continue |
| | [[ "$line" == *"$BINARY_PATH"* ]] && continue |
| |
|
| | |
| | LIB_PATH=$(echo "$line" | sed 's/^[[:space:]]*//' | cut -d' ' -f1) |
| |
|
| | |
| | [[ -z "$LIB_PATH" ]] && continue |
| |
|
| | |
| | |
| | |
| | if [[ "$LIB_PATH" == /usr/lib/* ]]; then |
| | log "$PASS System: $(basename "$LIB_PATH") (shared cache)" |
| | elif [[ "$LIB_PATH" == /System/Library/* ]]; then |
| | if [ -d "${LIB_PATH%/*}" ] || [ -f "$LIB_PATH" ]; then |
| | log "$PASS Framework: $(echo "$LIB_PATH" | grep -o '[^/]*\.framework')" |
| | else |
| | log "$FAIL MISSING: $LIB_PATH" |
| | MISSING_DEPS=$((MISSING_DEPS + 1)) |
| | fi |
| | elif [[ "$LIB_PATH" == @rpath/* ]] || [[ "$LIB_PATH" == @loader_path/* ]] || [[ "$LIB_PATH" == @executable_path/* ]]; then |
| | log "$WARN Relative: $LIB_PATH" |
| | elif [ -f "$LIB_PATH" ]; then |
| | log "$PASS External: $LIB_PATH" |
| | else |
| | log "$FAIL MISSING: $LIB_PATH" |
| | MISSING_DEPS=$((MISSING_DEPS + 1)) |
| | fi |
| | done < <(otool -L "$BINARY_PATH" 2>/dev/null | sort -u) |
| |
|
| | if [ $MISSING_DEPS -gt 0 ]; then |
| | log "" |
| | log "${RED}$FAIL Found $MISSING_DEPS missing dependencies!${NC}" |
| | else |
| | log "" |
| | log "${GREEN}$PASS All dependencies found${NC}" |
| | fi |
| | fi |
| |
|
| | |
| | |
| | |
| | print_section "Code Signing & Notarization" |
| |
|
| | CODESIGN_OUTPUT=$(codesign -dv --verbose=4 "$PLUGIN_PATH" 2>&1) |
| | SIGNING_ISSUE=0 |
| |
|
| | |
| | if echo "$CODESIGN_OUTPUT" | grep -q "Authority="; then |
| | |
| | log "${BLUE}Certificate Chain:${NC}" |
| | echo "$CODESIGN_OUTPUT" | grep "Authority=" | while read -r line; do |
| | CERT=$(echo "$line" | cut -d= -f2) |
| | log " $CERT" |
| | done |
| |
|
| | |
| | TEAM_ID=$(echo "$CODESIGN_OUTPUT" | grep "TeamIdentifier=" | cut -d= -f2) |
| | if [ -n "$TEAM_ID" ] && [ "$TEAM_ID" != "not set" ]; then |
| | log "$PASS Team ID: $TEAM_ID" |
| | else |
| | log "$WARN Team ID not set" |
| | fi |
| |
|
| | |
| | SIGN_TIMESTAMP=$(echo "$CODESIGN_OUTPUT" | grep "Timestamp=" | cut -d= -f2) |
| | if [ -n "$SIGN_TIMESTAMP" ]; then |
| | log "$PASS Signed on: $SIGN_TIMESTAMP" |
| | else |
| | log "$WARN No timestamp (signature may expire with certificate)" |
| | fi |
| |
|
| | |
| | RUNTIME=$(echo "$CODESIGN_OUTPUT" | grep "Runtime Version=" | cut -d= -f2) |
| | if [ -n "$RUNTIME" ]; then |
| | log "$PASS Hardened Runtime: $RUNTIME" |
| | else |
| | log "$WARN Hardened runtime not enabled" |
| | fi |
| |
|
| | |
| | if echo "$CODESIGN_OUTPUT" | grep -q "Notarization Ticket"; then |
| | log "$PASS Notarization ticket stapled" |
| | else |
| | log "$WARN Notarization ticket NOT stapled" |
| | SIGNING_ISSUE=1 |
| | fi |
| |
|
| | elif echo "$CODESIGN_OUTPUT" | grep -q "adhoc"; then |
| | log "$WARN Ad-hoc signed (development only)" |
| | SIGNING_ISSUE=1 |
| | else |
| | log "$FAIL NOT SIGNED" |
| | SIGNING_ISSUE=1 |
| | fi |
| |
|
| | |
| | log "" |
| | log "${BLUE}Signature Verification:${NC}" |
| | VERIFY_OUTPUT=$(codesign --verify --deep --strict "$PLUGIN_PATH" 2>&1) |
| | if [ $? -eq 0 ]; then |
| | log "$PASS Signature integrity: valid" |
| | else |
| | log "$FAIL Signature integrity: INVALID" |
| | log " $VERIFY_OUTPUT" |
| | SIGNING_ISSUE=1 |
| | fi |
| |
|
| | |
| | log "" |
| | log "${BLUE}Gatekeeper Assessment:${NC}" |
| | SPCTL_OUTPUT=$(spctl --assess --type execute -v "$PLUGIN_PATH" 2>&1) |
| | SPCTL_EXIT=$? |
| | if [ $SPCTL_EXIT -eq 0 ]; then |
| | log "$PASS Gatekeeper: accepted" |
| | elif echo "$SPCTL_OUTPUT" | grep -q "rejected"; then |
| | |
| | if echo "$SPCTL_OUTPUT" | grep -q "notarized"; then |
| | log "$WARN Gatekeeper: requires notarization" |
| | elif echo "$SPCTL_OUTPUT" | grep -q "not.*app"; then |
| | log "$PASS Gatekeeper: valid code (not an app bundle)" |
| | else |
| | log "$FAIL Gatekeeper: rejected" |
| | log " $SPCTL_OUTPUT" |
| | fi |
| | else |
| | log "$INFO Gatekeeper: $SPCTL_OUTPUT" |
| | fi |
| |
|
| | |
| | log "" |
| | log "${BLUE}Notarization Status (online check):${NC}" |
| | STAPLER_OUTPUT=$(xcrun stapler validate "$PLUGIN_PATH" 2>&1) |
| | if echo "$STAPLER_OUTPUT" | grep -q "valid"; then |
| | log "$PASS Notarization: verified" |
| | elif echo "$STAPLER_OUTPUT" | grep -q "not valid"; then |
| | log "$FAIL Notarization: NOT valid or not notarized" |
| | SIGNING_ISSUE=1 |
| | else |
| | log "$INFO $STAPLER_OUTPUT" |
| | fi |
| |
|
| | |
| | |
| | |
| | print_section "Quarantine Status" |
| |
|
| | QUARANTINE=$(xattr -p com.apple.quarantine "$PLUGIN_PATH" 2>/dev/null || echo "") |
| |
|
| | if [ -n "$QUARANTINE" ]; then |
| | log "$WARN Quarantine flag is SET" |
| | log " Value: $QUARANTINE" |
| | log "" |
| | log "${YELLOW}To remove quarantine, run:${NC}" |
| | log " xattr -cr \"$PLUGIN_PATH\"" |
| | else |
| | log "$PASS No quarantine flag" |
| | fi |
| |
|
| | |
| | |
| | |
| | print_section "Info.plist Analysis" |
| |
|
| | if [ -f "$PLIST_PATH" ]; then |
| | |
| | BUNDLE_ID=$(/usr/libexec/PlistBuddy -c "Print :CFBundleIdentifier" "$PLIST_PATH" 2>/dev/null || echo "") |
| | if [ -n "$BUNDLE_ID" ] && [ "$BUNDLE_ID" != "" ]; then |
| | log "$PASS CFBundleIdentifier: $BUNDLE_ID" |
| | else |
| | log "$FAIL CFBundleIdentifier is EMPTY!" |
| | log " ${YELLOW}This may cause loading issues on some systems${NC}" |
| | fi |
| |
|
| | |
| | BUNDLE_EXEC=$(/usr/libexec/PlistBuddy -c "Print :CFBundleExecutable" "$PLIST_PATH" 2>/dev/null || echo "") |
| | if [ "$BUNDLE_EXEC" = "$PLUGIN_NAME" ]; then |
| | log "$PASS CFBundleExecutable: $BUNDLE_EXEC" |
| | else |
| | log "$WARN CFBundleExecutable: $BUNDLE_EXEC (expected: $PLUGIN_NAME)" |
| | fi |
| |
|
| | |
| | MIN_VERSION=$(/usr/libexec/PlistBuddy -c "Print :LSMinimumSystemVersion" "$PLIST_PATH" 2>/dev/null || echo "not set") |
| | log "$INFO Minimum macOS: $MIN_VERSION" |
| |
|
| | |
| | CURRENT_MACOS=$(sw_vers -productVersion) |
| | log "$INFO Current macOS: $CURRENT_MACOS" |
| | fi |
| |
|
| | |
| | |
| | |
| | print_section "Entry Point" |
| |
|
| | if [ -f "$BINARY_PATH" ]; then |
| | if nm "$BINARY_PATH" 2>/dev/null | grep -q "_EffectMain"; then |
| | log "$PASS EffectMain symbol exported" |
| | elif nm "$BINARY_PATH" 2>/dev/null | grep -q "_main"; then |
| | log "$WARN Found _main but not _EffectMain" |
| | else |
| | log "$FAIL No EffectMain symbol found!" |
| | fi |
| | fi |
| |
|
| | |
| | |
| | |
| | print_section "File Permissions & Ownership" |
| |
|
| | PERM_ISSUES=0 |
| | CURRENT_USER=$(whoami) |
| |
|
| | log "${BLUE}All files in plugin bundle:${NC}" |
| | log "" |
| |
|
| | |
| | while IFS= read -r item; do |
| | |
| | STAT_OUTPUT=$(stat -f "%Sp %Su %Sg" "$item" 2>/dev/null) |
| | PERMS=$(echo "$STAT_OUTPUT" | cut -d' ' -f1) |
| | OWNER=$(echo "$STAT_OUTPUT" | cut -d' ' -f2) |
| | GROUP=$(echo "$STAT_OUTPUT" | cut -d' ' -f3) |
| |
|
| | |
| | REL_PATH="${item#$PLUGIN_PATH}" |
| | [ -z "$REL_PATH" ] && REL_PATH="/" |
| |
|
| | |
| | HAS_ISSUE=0 |
| |
|
| | |
| | if [ -d "$item" ]; then |
| | ITEM_TYPE="d" |
| | |
| | if [[ "$PERMS" != d*r?x*r?x*r?x* ]] && [[ "$PERMS" != d*r?x*r?x* ]]; then |
| | HAS_ISSUE=1 |
| | fi |
| | else |
| | |
| | if [[ "$PERMS" != -*r* ]]; then |
| | HAS_ISSUE=1 |
| | fi |
| | |
| | if [ "$item" = "$BINARY_PATH" ] && [[ "$PERMS" != -*x* ]]; then |
| | HAS_ISSUE=1 |
| | fi |
| | fi |
| |
|
| | |
| | if [ $HAS_ISSUE -eq 1 ]; then |
| | log "$FAIL $PERMS $OWNER:$GROUP $REL_PATH" |
| | PERM_ISSUES=$((PERM_ISSUES + 1)) |
| | else |
| | log "$PASS $PERMS $OWNER:$GROUP $REL_PATH" |
| | fi |
| |
|
| | done < <(find "$PLUGIN_PATH" -print 2>/dev/null) |
| |
|
| | |
| | log "" |
| | if [ $PERM_ISSUES -eq 0 ]; then |
| | log "${GREEN}$PASS All permissions look correct${NC}" |
| | else |
| | log "${RED}$FAIL Found $PERM_ISSUES permission issue(s)${NC}" |
| | log "" |
| | log "${YELLOW}To fix permissions, run:${NC}" |
| | log " sudo chmod -R a+rX \"$PLUGIN_PATH\"" |
| | log " sudo chmod a+x \"$BINARY_PATH\"" |
| | fi |
| |
|
| | |
| | log "" |
| | log "${BLUE}Ownership Summary:${NC}" |
| | |
| | OWNERS=$(find "$PLUGIN_PATH" -print0 2>/dev/null | xargs -0 stat -f "%Su" | sort -u) |
| | for owner in $OWNERS; do |
| | COUNT=$(find "$PLUGIN_PATH" -user "$owner" 2>/dev/null | wc -l | tr -d ' ') |
| | log " $owner: $COUNT items" |
| | done |
| |
|
| | |
| | |
| | |
| | print_section "Extended Attributes" |
| |
|
| | |
| | XATTR_FILES=0 |
| | log "${BLUE}Checking for extended attributes on all files...${NC}" |
| | log "" |
| |
|
| | while IFS= read -r item; do |
| | XATTRS=$(xattr "$item" 2>/dev/null) |
| | if [ -n "$XATTRS" ]; then |
| | REL_PATH="${item#$PLUGIN_PATH}" |
| | [ -z "$REL_PATH" ] && REL_PATH="/" |
| |
|
| | log "$WARN $REL_PATH" |
| | echo "$XATTRS" | while read -r attr; do |
| | if [ -n "$attr" ]; then |
| | log " $attr" |
| | fi |
| | done |
| | XATTR_FILES=$((XATTR_FILES + 1)) |
| | fi |
| | done < <(find "$PLUGIN_PATH" -print 2>/dev/null) |
| |
|
| | if [ $XATTR_FILES -eq 0 ]; then |
| | log "${GREEN}$PASS No extended attributes found${NC}" |
| | else |
| | log "" |
| | log "${YELLOW}Found extended attributes on $XATTR_FILES file(s)${NC}" |
| | log "${YELLOW}To remove all extended attributes, run:${NC}" |
| | log " xattr -cr \"$PLUGIN_PATH\"" |
| | fi |
| |
|
| | |
| | |
| | |
| | print_header "Summary" |
| |
|
| | ISSUES=0 |
| |
|
| | |
| | if [ -z "$BUNDLE_ID" ] || [ "$BUNDLE_ID" = "" ]; then |
| | log "$FAIL Empty CFBundleIdentifier - may cause 'entry point' errors" |
| | ISSUES=$((ISSUES + 1)) |
| | fi |
| |
|
| | if [ -n "$QUARANTINE" ]; then |
| | log "$WARN Quarantine flag set - may block plugin loading" |
| | ISSUES=$((ISSUES + 1)) |
| | fi |
| |
|
| | if [ $MISSING_DEPS -gt 0 ]; then |
| | log "$FAIL Missing dependencies detected" |
| | ISSUES=$((ISSUES + 1)) |
| | fi |
| |
|
| | if [ $SIGNING_ISSUE -gt 0 ]; then |
| | log "$WARN Code signing or notarization issues detected" |
| | ISSUES=$((ISSUES + 1)) |
| | fi |
| |
|
| | if [ $PERM_ISSUES -gt 0 ]; then |
| | log "$FAIL Permission issues detected" |
| | ISSUES=$((ISSUES + 1)) |
| | fi |
| |
|
| | if [ $ISSUES -eq 0 ]; then |
| | log "${GREEN}$PASS No issues detected${NC}" |
| | else |
| | log "" |
| | log "${YELLOW}Found $ISSUES potential issue(s)${NC}" |
| | log "" |
| | log "${BLUE}Quick fixes:${NC}" |
| | if [ -n "$QUARANTINE" ]; then |
| | log " Remove quarantine: xattr -cr \"$PLUGIN_PATH\"" |
| | fi |
| | if [ $PERM_ISSUES -gt 0 ]; then |
| | log " Fix permissions: sudo chmod -R a+rX \"$PLUGIN_PATH\"" |
| | fi |
| | fi |
| |
|
| | |
| | |
| | |
| | log "" |
| | log "βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ" |
| | log "" |
| | log "${GREEN}π Report saved to:${NC}" |
| | log " $OUTPUT_FILE" |
| | log "" |
| | log "${YELLOW}Please send this file to support for analysis.${NC}" |
| | log "" |
| |
|
| | |
| | echo "" |
| | echo "ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ" |
| | echo "" |
| | echo "π Report saved to Desktop:" |
| | echo " $OUTPUT_FILE" |
| | echo "" |
| | echo "π Please send this file to BSKL support for analysis." |
| | echo "" |
| |
|