#!/bin/bash if [[ $EUID -ne 0 ]]; then echo "๐Ÿ”‘ This script requires administrator rights. Please enter your password:" exec sudo "$0" "$@" exit 1 fi echo "......................................." echo "macOS errorfix v1.7.3 with ($SHELL)" [ -n "$BASH_VERSION" ] && echo "bash version $BASH_VERSION" [ -n "$ZSH_VERSION" ] && echo "zsh version $ZSH_VERSION" OS_version=$(sw_vers | awk '/ProductVersion/ {print $2}') || true [ -z "$OS_version" ] && OS_version="(Unknown)" architecture=$(uname -m) echo "OS Version: $OS_version" echo "Architecture: $architecture" echo "......................................." echo "๐Ÿ” Checking if Docker is installed." if ! command -v docker &> /dev/null; then echo "โŒ Error: Docker command not found. Please install Docker and try again." exit 1 else echo "โœ… Docker is installed." fi echo "๐Ÿ” Checking if jq is installed." if ! command -v jq &>/dev/null; then if command -v brew &>/dev/null; then echo "๐Ÿ› ๏ธ Installing jq..." brew install jq >/dev/null else echo "โš ๏ธ jq is not installed." fi else echo "โœ… jq is installed." fi server_ip="127.0.0.1" hostname="studio-app.snapchat.com" server_url="https://$hostname" app_path="/Applications/Snap Camera.app" binary_path="$app_path/Contents/MacOS" binary_file="$binary_path/Snap Camera" cert_file="$hostname.crt" if pgrep -x "Snap Camera" > /dev/null; then echo "โš ๏ธ Snap Camera is running. Terminating application." pkill -x "Snap Camera" fi if [ ! -d "$app_path" ]; then echo "โŒ Error: Snap Camera.app directory does not exist." echo "๐ŸŒ Please download and install from: https://bit.ly/snpcm" exit 1 fi if [ ! -f "$binary_file" ]; then echo "โŒ Error: Snap Camera binary does not exist." echo "๐ŸŒ Please re-download and install from: https://bit.ly/snpcm" exit 1 fi function to_posix_path() { local path="$1" local resolved_path="" if command -v greadlink >/dev/null 2>&1; then resolved_path=$(greadlink -f "$path") elif command -v perl >/dev/null 2>&1; then resolved_path=$(perl -MCwd=realpath -e 'print realpath($ARGV[0])' "$path") elif [[ -d "$path" ]]; then resolved_path=$(cd "$path" && pwd -P) elif [[ -f "$path" ]]; then resolved_path="$(cd "$(dirname "$path")" && pwd -P)/$(basename "$path")" fi echo "${resolved_path%/}" } function verify_directory() { local dir dir=$(to_posix_path "$1") if [ -d "$dir" ] && [ -f "$dir/server.js" ] && [ -d "$dir/ssl" ]; then return 0 else return 1 fi } function is_container_running() { local container_id container_id=$(docker ps -q --filter "name=snap" --filter "name=webapp" | head -n 1) if [[ -n "$container_id" ]]; then local running running=$(docker inspect --format '{{.State.Running}}' "$container_id" 2>/dev/null) [[ "$running" == "true" ]] && return 0 fi return 1 } echo "๐Ÿ” Trying to detect Docker webapp container." container_id=$(docker ps -q -a --filter "name=snap" --filter "name=webapp" | head -n 1) if [[ -n "$container_id" ]]; then running=$(docker inspect --format '{{.State.Running}}' "$container_id") if [[ "$running" == "true" ]]; then echo "โœ… Snap Camera Server is running: $container_id" else echo "โš ๏ธ Snap Camera Server is not runnning: $container_id" fi else echo "โš ๏ธ Unable to auto-detect Snap Camera Server on your system." fi echo "๐Ÿ” Trying to determine server directory." project_dir=$(docker inspect --format '{{ index .Config.Labels "com.docker.compose.project.working_dir" }}' "$container_id" 2>/dev/null) if [[ -n "$project_dir" ]]; then echo "๐Ÿ“ Found: '$project_dir'." project_dir=$(to_posix_path "$project_dir") fi if [ -z "$project_dir" ] || [ ! -d "$project_dir" ] || ! verify_directory "$project_dir"; then echo "โš ๏ธ The server directory could not be determined automatically." while true; do user_input=$(osascript -e 'tell app "Finder" to set folderPath to POSIX path of (choose folder with prompt "Please select the Snap Camera Server directory:")' 2>/dev/null) if [[ $? -ne 0 ]]; then echo "โŒ User canceled directory selection." exit 1 fi user_input=$(echo "$user_input" | sed 's/^ *//g' | sed 's/ *$//g') if verify_directory "$user_input"; then project_dir="${user_input%/}" break else echo "โš ๏ธ Invalid directory: '$user_input'!" fi done fi echo "โœ… Snap Camera Server directory: $project_dir" echo "๐Ÿ” Checking if an .env file exists." env_path="$project_dir/.env" example_env_path="$project_dir/example.env" if [[ ! -f "$env_path" ]]; then echo "โš ๏ธ An .env file was not found." if [[ -f "$example_env_path" ]]; then cp "$example_env_path" "$env_path" echo "โœ… An .env file was created from example.env." else echo "โŒ Error: Neither .env nor example.env found." exit 1 fi else echo "โœ… An .env file exists." fi echo "๐Ÿ” Checking if a '/etc/hosts' entry exists." if grep -E -q "^$server_ip[[:space:]]+$hostname" /etc/hosts; then echo "โœ… '/etc/hosts' entry $server_ip $hostname exists." else echo "โš ๏ธ '/etc/hosts' entry $server_ip $hostname does not exist." echo "$server_ip $hostname" | sudo tee -a /etc/hosts if grep -E -q "^$server_ip[[:space:]]+$hostname" /etc/hosts; then echo "โœ… '/etc/hosts' entry $server_ip $hostname was created." else echo "โŒ Error: Failed to create '/etc/hosts' entry." exit 1 fi fi echo "๐Ÿ” Checking if an SSL certificate is present." cert_path="$project_dir/ssl/$cert_file" gen_cert_script="$project_dir/gencert.sh" if [[ ! -f "$cert_path" ]]; then echo "โš ๏ธ SSL certificate is missing." chmod +x "$gen_cert_script" if [[ -x "$gen_cert_script" ]]; then echo "๐Ÿ”„ Generating new SSL certificate..." (cd "$project_dir" && ./gencert.sh) else echo "โŒ Error: SSL certificate missing and gencert.sh is not executable or does not exist." exit 1 fi else echo "โœ… SSL certificate found." fi echo "๐Ÿ› ๏ธ Fixing possible SSL access right issues." sudo chown -R $(id -un):$(id -gn) "$project_dir/ssl/*" echo "๐Ÿ› ๏ธ Fixing possible SSL trust issues..." cert_hash=$(openssl x509 -in "$cert_path" -noout -fingerprint -sha1 | sed 's/^.*=//') if [[ -z "$cert_hash" ]]; then echo "โŒ Error: Failed to read certificate fingerprint! Please check the certificate file." exit 1 else sudo security delete-certificate -c "$hostname" ~/Library/Keychains/login.keychain-db 2>/dev/null && echo "๐Ÿ—‘๏ธ Removed old '$hostname' certificate from Login Keychain." sudo security delete-certificate -Z "$cert_hash" ~/Library/Keychains/login.keychain-db 2>/dev/null && echo "๐Ÿ—‘๏ธ Removed old certificate from Login Keychain." sudo security delete-certificate -c "$hostname" /Library/Keychains/System.keychain 2>/dev/null && echo "๐Ÿ—‘๏ธ Removed old '$hostname' certificate from System Keychain." sudo security delete-certificate -Z "$cert_hash" /Library/Keychains/System.keychain 2>/dev/null && echo "๐Ÿ—‘๏ธ Removed old certificate from System Keychain." fi if sudo security add-trusted-cert -d -r trustRoot -k ~/Library/Keychains/login.keychain-db "$cert_path"; then echo "โœ… Imported and trusted certificate in Login Keychain." else echo "โŒ Error: Failed to mark certificate as trusted in Login Keychain!" exit 1 fi if sudo security add-trusted-cert -d -r trustRoot -k /Library/Keychains/System.keychain "$cert_path"; then echo "โœ… Imported and trusted certificate in System Keychain." else # Login Keychain should be sufficient echo "โš ๏ธ Warning: Failed to mark certificate as trusted in System Keychain!" fi if [ -f "$binary_path/Snap_Camera_real" ]; then echo "๐Ÿงพ ARM Wrapper script detected." binary_file="$binary_path/Snap_Camera_real" fi echo "๐Ÿ”„ Generating MD5 checksum of the Snap Camera binary file." if command -v md5sum > /dev/null; then md5_result=$(md5sum "$binary_file" | awk '{print $1}') else md5_result=$(md5 -q "$binary_file") fi if [ "$md5_result" = "8dc456e29478a0cdfaedefac282958e7" ]; then echo "โœ… MD5 checksum result: Original binary with original code signing." elif [ "$md5_result" = "15ad19c477d5d246358d68a711e29a6e" ]; then echo "โœ… MD5 checksum result: Original binary no code signing." elif [ "$md5_result" = "1ac420d1828a3d754e99793af098f830" ]; then echo "โœ… MD5 checksum result: Patched binary with original code signing." elif [ "$md5_result" = "e2ed1f2e502617392060270fa6e5e979" ]; then echo "โœ… MD5 checksum result: Patched binary no code signing." else echo "โš ๏ธ Unknown MD5 checksum '$md5_result'." fi echo "๐Ÿ› ๏ธ Making the Snap Camera binary executable." chmod +x "$binary_file" echo "๐Ÿ› ๏ธ Removing the macOS code signing." if ! sudo codesign --remove-signature "$app_path"; then echo "โš ๏ธ Directly removing signature from app bundle failed. Try recursively." if find "$app_path" -type f -perm +111 &>/dev/null; then perm_flag="+111" else perm_flag="/111" fi success=true while IFS= read -r file; do if ! sudo codesign --remove-signature "$file"; then echo "โŒ Error: removing signature for file: $file" success=false fi done < <(find "$app_path" -type f -perm $perm_flag) if $success; then echo "โœ… All signatures were successfully removed." else echo "โŒ Error: At least one file could not be freed from the signature." exit 1 fi else echo "โœ… Signature removal was successful." fi if [ "$architecture" == "arm64" ]; then echo "๐Ÿ” ARM architecture detected." if [ ! -f "$binary_path/Snap_Camera_real" ]; then echo "๐Ÿ› ๏ธ Creating x86 wrapper script..." mv "$binary_path/Snap Camera" "$binary_path/Snap_Camera_real" echo '#!/bin/bash arch -x86_64 "'"$binary_path/Snap_Camera_real"'" "$@"' > "$binary_path/Snap Camera" chmod +x "$binary_path/Snap Camera" binary_file="$binary_path/Snap_Camera_real" fi fi echo "๐Ÿ› ๏ธ Removing extended file attributes." sudo xattr -cr "$app_path" echo "๐Ÿ› ๏ธ Re-signing the Snap Camera application." if sudo codesign --force --deep --sign - "$app_path"; then echo "โœ… Re-signing was successful." else echo "โŒ Error: Re-signing failed." exit 1 fi echo "๐Ÿ”„ Re-Generating MD5 checksum of the Snap Camera binary file." if command -v md5sum > /dev/null; then md5_new=$(md5sum "$binary_file" | awk '{print $1}') else md5_new=$(md5 -q "$binary_file") fi echo "โœ… New MD5 checksum: '$md5_new'." echo "๐Ÿ› ๏ธ Adding Snap Camera to Gatekeeper exceptions." if sudo spctl --add "$app_path"; then echo "โœ… Snap Camera successfully added to Gatekeeper exceptions." else echo "โš ๏ธ Failed to add Snap Camera to Gatekeeper exceptions!" fi plugin_dir="/Library/CoreMediaIO/Plug-Ins/DAL" target_plugin="$plugin_dir/SnapCamera.plugin" source_plugin="$binary_path/SnapCamera.plugin" if [[ -d "$plugin_dir" && ! -e "$target_plugin" ]]; then echo "โš ๏ธ SnapCamera.plugin is missing." if [[ -d "$source_plugin" ]]; then echo "๐Ÿ› ๏ธ Re-installing Snap Camera Plugin." sudo cp -Rp "$source_plugin" "$plugin_dir" if [[ -d "$target_plugin" ]]; then sudo chown -R root:wheel "$target_plugin" sudo chmod -R 755 "$target_plugin" sudo xattr -dr com.apple.quarantine "$target_plugin" sudo spctl --add "$target_plugin" echo "โœ… SnapCamera.plugin successfully installed." else echo "โš ๏ธ Failed to re-install SnapCamera.plugin." fi else echo "โš ๏ธ Source plugin not found at $source_plugin." fi fi echo "๐Ÿ” Checking pf-rules." tmp_rules="/tmp/pf_rules.conf" sudo pfctl -sr 2>/dev/null > "$tmp_rules" if [ ! -s "$tmp_rules" ]; then echo "โœ… No pf rules found. Skipping pf check." else if grep -q "$hostname" "$tmp_rules"; then echo "โš ๏ธ Host $hostname is blocked by pf. Unblocking..." grep -v "$hostname" "$tmp_rules" | sudo tee "$tmp_rules.filtered" > /dev/null sudo pfctl -f "$tmp_rules.filtered" sudo pfctl -e echo "โœ… Host $hostname was unblocked." else echo "โœ… Host $hostname is not blocked by pf." fi fi echo "๐Ÿ” Checking firewall status." if [ -f "/Library/Preferences/com.apple.alf.plist" ]; then firewall_state=$(sudo defaults read /Library/Preferences/com.apple.alf globalstate 2>/dev/null) case "$firewall_state" in 0) echo "โœ… Firewall is disabled. Skipping firewall checks." ;; 1|2) echo "โœ… Firewall is enabled. Checking if Snap Camera is blocked..." blocked_apps=$(sudo defaults read /Library/Preferences/com.apple.alf.plist | grep -A2 "$app_path" | grep -i "block") if [[ -n "$blocked_apps" ]]; then echo "โš ๏ธ Snap Camera is blocked by firewall. Unblocking..." sudo /usr/libexec/ApplicationFirewall/socketfilterfw --unblockapp "$app_path" echo "โœ… Snap Camera was unblocked." else echo "โœ… Snap Camera is not blocked by firewall." fi if [[ "$firewall_state" -eq 2 ]]; then echo "โš ๏ธ Firewall is in strict mode. Ensuring that Snap Camera is allowed..." sudo /usr/libexec/ApplicationFirewall/socketfilterfw --add "$app_path" sudo /usr/libexec/ApplicationFirewall/socketfilterfw --unblockapp "$app_path" echo "โœ… Snap Camera was explicitly allowed in the firewall." fi ;; *) echo "โš ๏ธ Unknown firewall state: $firewall_state. Skipping firewall checks." ;; esac else echo "โš ๏ธ Firewall configuration file not found. Skipping firewall checks." fi echo "๐Ÿ” Checking Docker file sharing directories." docker_restart_required="false" if ! command -v jq &>/dev/null; then echo "โš ๏ธ jq is not installed. Skipping Docker file sharing check." else docker_settings="$HOME/Library/Group Containers/group.com.docker/settings.json" if [[ -f "$docker_settings" ]]; then if jq -e --arg folder "$project_dir" '.filesharingDirectories | index($folder) != null' "$docker_settings" &>/dev/null; then echo "โœ… '$project_dir' is already in the Docker whitelist." else echo "๐Ÿ› ๏ธ Adding '$project_dir' to Docker whitelist." cp "$docker_settings" "$docker_settings.bak" temp_settings=$(mktemp) && mv "$temp_settings" "${temp_settings}.json" && temp_settings="${temp_settings}.json" jq --arg folder "$project_dir" '.filesharingDirectories += [$folder]' "$docker_settings" > "$temp_settings" if jq empty "$temp_settings" &>/dev/null; then mv "$temp_settings" "$docker_settings" echo "โœ… Server directory added successfully." docker_restart_required="true" else echo "โš ๏ธ JSON validation failed! Changes were not applied." fi rm -f "$temp_settings" fi else echo "โš ๏ธ Docker settings.json not found!" fi fi if pgrep -x "Docker" > /dev/null && [ "$docker_restart_required" == "true" ]; then echo "๐Ÿ”„ Restarting Docker..." osascript -e 'quit app "Docker"' & disown echo "โณ Waiting for Docker to close..." timeout=60 while docker system info &>/dev/null; do sleep 1 ((timeout--)) if [ $timeout -le 0 ]; then echo "โŒ Timeout reached. Docker did not close successfully." exit 1 fi done echo "โœ… Docker closed successfully." fi if ! pgrep -x "Docker" > /dev/null; then echo "๐Ÿš€ Starting Docker in the background..." open -a Docker & disown echo "โณ Waiting for Docker to start..." timeout=60 while ! docker system info &>/dev/null; do sleep 1 ((timeout--)) if [ $timeout -le 0 ]; then echo "โŒ Timeout reached. Docker did not start successfully." exit 1 fi done echo "โœ… Docker started successfully." fi if ! is_container_running; then echo "๐Ÿš€ Starting the server with 'docker compose up'." (cd "$project_dir" && docker compose up -d) max_retries=10 retries=0 echo "โณ Waiting for the server to start... " while [[ $retries -lt $max_retries ]]; do if is_container_running; then echo "โœ… Snap Camera Server is now running." break fi ((retries++)) sleep 5 done if ! is_container_running; then echo "โŒ Error: Snap Camera Server did not start within the expected time." exit 1 fi fi echo "๐Ÿ” Sending ping to host $hostname." if ping -c 1 -W 2000 "$hostname" > /dev/null 2>&1; then echo "โœ… Ping to host $hostname succesful." else echo "โš ๏ธ Ping to host $hostname failed." fi echo "๐Ÿ” Sending request to host $server_url." if command -v curl > /dev/null; then server_response=$(curl -s -o /dev/null -w "%{http_code}" --connect-timeout 5 --max-time 10 "$server_url" 2>&1) if [[ "$server_response" == "000" ]]; then echo "โŒ Error: The server $server_url cannot be reached. Checking details..." echo "๐Ÿ” Running: curl -v --connect-timeout 5 $server_url" curl -v --connect-timeout 5 "$server_url" echo "๐Ÿ” Running: curl -v --insecure --connect-timeout 5 $server_url" curl -v --insecure --connect-timeout 5 "$server_url" exit 1 elif [[ "$server_response" =~ ^[0-9]{3}$ ]]; then if [[ "$server_response" != "200" ]]; then echo "โŒ Error: The server $server_url responded with status: $server_response" exit 1 else echo "โœ… The server $server_url is reachable." fi else echo "โŒ Error: The server $server_url cannot be reached:" echo "$server_response" exit 1 fi else echo "โš ๏ธ Warning: The 'curl' command is not available. Please check in your browser that the URL $server_url is accessible." fi echo "๐Ÿ” Checking System Integrity Protection (SIP) status." sip_status=$(csrutil status | grep -o "enabled") if [[ "$sip_status" == "enabled" ]]; then echo "โš ๏ธ Warning: System Integrity Protection (SIP) is enabled. Some operations may be restricted!" else echo "โœ… System Integrity Protection (SIP) is disabled." fi echo "๐Ÿ” Checking virtual webcam installation." system_profiler SPCameraDataType | grep -i -A 5 Snap echo "๐Ÿ”„ Killing/Restarting camera related processes..." sudo killall VDCAssistant AppleCameraAssistant 2>/dev/null sudo launchctl kickstart -k system/com.apple.appleh13camerad 2>/dev/null echo "๐Ÿ” Checking 'appleh13camerad' service." if [ -f "/System/Library/LaunchDaemons/com.apple.appleh13camerad.plist" ]; then if sudo launchctl list | grep -q "com.apple.appleh13camerad"; then echo "โœ… The service 'appleh13camerad' is running." else echo "โš ๏ธ The service 'appleh13camerad' is not running." echo "๐Ÿ”„ Attempting to start the service..." sudo launchctl bootstrap system "/System/Library/LaunchDaemons/com.apple.appleh13camerad.plist" if sudo launchctl list | grep -q "com.apple.appleh13camerad"; then echo "โœ… Service 'appleh13camerad' successfully started." else echo "โš ๏ธ Failed to start the service." fi fi fi if [ "$architecture" == "arm64" ]; then echo "๐Ÿš€ Starting Snap Camera application with Rosetta..." arch -x86_64 "$binary_file" & disown else echo "๐Ÿš€ Starting Snap Camera..." open "$app_path" & disown fi echo "๐Ÿ†— If you continue to have problems, please re-download and re-install Snap Camera from:" echo "๐ŸŒ https://bit.ly/snpcm"