Files
simple-sshd/scripts/update_package_name.sh
2025-04-07 15:50:54 +12:00

487 lines
20 KiB
Bash
Executable File
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/bin/bash
# Script to update the package name across the entire project
# Author: Goose
# Updated: 2025-04-07
#
# This script updates all package references in the project,
# including Java files, Gradle configuration, AndroidManifest.xml,
# and most importantly, the JNI function signatures in native code.
#
# Usage: ./scripts/update_package_name.sh
# Note: The new package name should be defined in the env.txt file as: PACKAGE_NAME='your.package.name'
set -e # Exit on error
# Get the root directory of the project (one level up from scripts directory)
ROOT_DIR=$(dirname "$(dirname "$(readlink -f "$0")")")
cd $ROOT_DIR
echo "===================================================="
echo "SimpleSSHD Package Name Update Script"
echo "===================================================="
echo "This script updates all package references in the project,"
echo "including in Java files, Gradle configuration, and"
echo "native JNI function signatures (important for native code)."
echo "===================================================="
# Load package name from .env file
if [ -f "env.txt" ]; then
source env.txt
else
echo "ERROR: env.txt file not found. Please create it with PACKAGE_NAME='your.package.name'"
exit 1
fi
if [ -z "$PACKAGE_NAME" ]; then
echo "ERROR: PACKAGE_NAME not defined in env.txt"
exit 1
fi
echo "Updating package name to: $PACKAGE_NAME"
# Validate package name format
if [[ ! $PACKAGE_NAME =~ ^[a-z][a-z0-9_]*(\.[a-z][a-z0-9_]*)*$ ]]; then
echo "ERROR: Invalid package name format: $PACKAGE_NAME"
echo "Package name must be in the format like 'com.example.app'"
exit 1
fi
# Store the current package name from build.gradle
GRADLE_PACKAGE=$(grep -m 1 "applicationId" ./app/build.gradle | sed -E 's/.*"([^"]+)".*/\1/')
if [ -z "$GRADLE_PACKAGE" ]; then
echo "ERROR: Could not determine package name from build.gradle"
exit 1
fi
echo "Package name in build.gradle: $GRADLE_PACKAGE"
# Find the actual Java package by examining a source file
FIRST_JAVA_FILE=$(find ./app/src/main/java -name "*.java" -type f | head -1)
if [ -z "$FIRST_JAVA_FILE" ]; then
echo "ERROR: Could not find any Java files in the project"
exit 1
fi
PACKAGE_LINE=$(grep -m 1 "^package" "$FIRST_JAVA_FILE" || echo "package unknown;")
CURRENT_PACKAGE=$(echo "$PACKAGE_LINE" | sed -E 's/package ([^;]+);/\1/')
# Determine the source directory
CURRENT_PACKAGE_PATH=${CURRENT_PACKAGE//./\/}
CURRENT_PACKAGE_DIR="./app/src/main/java/$CURRENT_PACKAGE_PATH"
echo "Actual package used in Java files: $CURRENT_PACKAGE"
echo "Source directory: $CURRENT_PACKAGE_DIR"
# Check if package name is already set to the desired value
if [ "$CURRENT_PACKAGE" = "$PACKAGE_NAME" ] && [ "$GRADLE_PACKAGE" = "$PACKAGE_NAME" ]; then
echo "Package name is already set to $PACKAGE_NAME. No changes needed."
exit 0
fi
# Create backup directory
BACKUP_DIR="./backups/package_backup_$(date +%Y%m%d%H%M%S)"
echo "Creating backup in: $BACKUP_DIR"
mkdir -p "$BACKUP_DIR/app/src/main/java/$CURRENT_PACKAGE_PATH"
# Backup key files
cp -v ./app/src/main/AndroidManifest.xml "$BACKUP_DIR/app/src/main/"
cp -v ./app/build.gradle "$BACKUP_DIR/app/"
# Backup Java files
cp -rv "$CURRENT_PACKAGE_DIR"/* "$BACKUP_DIR/app/src/main/java/$CURRENT_PACKAGE_PATH/"
# Backup JNI files
mkdir -p "$BACKUP_DIR/jni"
cp -rv ./jni/* "$BACKUP_DIR/jni/"
# Backup native libs
mkdir -p "$BACKUP_DIR/libs"
if [ -d "./app/src/main/lib" ]; then
cp -rv ./app/src/main/lib/* "$BACKUP_DIR/libs/" 2>/dev/null || true
fi
echo "Backup completed. Proceeding with package name update..."
# Update build.gradle
echo "Updating build.gradle..."
sed -i "s/applicationId \"$GRADLE_PACKAGE\"/applicationId \"$PACKAGE_NAME\"/g" ./app/build.gradle
# Update AndroidManifest.xml
echo "Updating AndroidManifest.xml..."
sed -i "s/package=\".*\"/package=\"$PACKAGE_NAME\"/g" ./app/src/main/AndroidManifest.xml
# Update intent filters and broadcast receivers in AndroidManifest.xml
echo "Updating intent filters and broadcast receivers..."
sed -i "s/android:name=\"$CURRENT_PACKAGE/android:name=\"$PACKAGE_NAME/g" ./app/src/main/AndroidManifest.xml
sed -i "s/<action android:name=\"$CURRENT_PACKAGE/<action android:name=\"$PACKAGE_NAME/g" ./app/src/main/AndroidManifest.xml
# Create the destination directory for Java files
NEW_PACKAGE_PATH=${PACKAGE_NAME//./\/}
NEW_PACKAGE_DIR="./app/src/main/java/$NEW_PACKAGE_PATH"
mkdir -p "$NEW_PACKAGE_DIR"
echo "Moving Java files from $CURRENT_PACKAGE_DIR to $NEW_PACKAGE_DIR"
# Copy all the Java files to the new package path
if [ -d "$CURRENT_PACKAGE_DIR" ]; then
# Copy all Java files
cp -rv "$CURRENT_PACKAGE_DIR"/* "$NEW_PACKAGE_DIR/"
# Update package declarations in all Java files
echo "Updating package declarations in Java files..."
find "$NEW_PACKAGE_DIR" -name "*.java" -type f -exec sed -i "s/^package $CURRENT_PACKAGE;/package $PACKAGE_NAME;/g" {} \;
# Update import statements for the same package
echo "Updating import statements in Java files..."
find "$NEW_PACKAGE_DIR" -name "*.java" -type f -exec sed -i "s/import $CURRENT_PACKAGE/import $PACKAGE_NAME/g" {} \;
# Only remove old directory if it's different from the new one
if [ "$CURRENT_PACKAGE_DIR" != "$NEW_PACKAGE_DIR" ]; then
echo "Removing old package directory: $CURRENT_PACKAGE_DIR"
rm -rf "$CURRENT_PACKAGE_DIR"
# Clean up empty parent directories
PARENT_DIR=$(dirname "$CURRENT_PACKAGE_DIR")
while [[ "$PARENT_DIR" != "./app/src/main/java" && "$PARENT_DIR" != "./app/src/main" && "$PARENT_DIR" != "./app/src" && "$PARENT_DIR" != "./app" && "$PARENT_DIR" != "." ]]; do
if [ -z "$(ls -A "$PARENT_DIR")" ]; then
echo "Removing empty directory: $PARENT_DIR"
rm -rf "$PARENT_DIR"
PARENT_DIR=$(dirname "$PARENT_DIR")
else
break
fi
done
fi
else
echo "ERROR: Source directory $CURRENT_PACKAGE_DIR does not exist."
echo "Please check if the Java source files are in the expected location."
exit 1
fi
# ****************** CRITICAL JNI HANDLING ******************
echo "Processing native code and JNI references..."
# Generate the proper JNI package name encodings
# For packages with underscores, this is critical to get right
_generate_proper_jni_encodings() {
# Generate path-style encoding (/ instead of .)
CURRENT_JNI_CLASSPATH="${CURRENT_PACKAGE//./\/}"
NEW_JNI_CLASSPATH="${PACKAGE_NAME//./\/}"
# The correct JNI method prefix format should NOT have _1 between package components
# It should be: Java_com_android_sshd_server_test006 NOT Java_com_1android_1sshd_1server_1test006
CURRENT_JNI_PACKAGE="${CURRENT_PACKAGE//./\_}"
NEW_JNI_PACKAGE="${PACKAGE_NAME//./\_}"
# These are kept for compatibility with existing uses in the script
CURRENT_JNI_METHOD_PREFIX="Java_${CURRENT_JNI_PACKAGE}"
NEW_JNI_METHOD_PREFIX="Java_${NEW_JNI_PACKAGE}"
echo "Generated JNI encodings:"
echo " Current package: $CURRENT_PACKAGE"
echo " New package: $PACKAGE_NAME"
echo " Current JNI classpath: $CURRENT_JNI_CLASSPATH"
echo " New JNI classpath: $NEW_JNI_CLASSPATH"
echo " Current JNI package encoding: $CURRENT_JNI_PACKAGE"
echo " New JNI package encoding: $NEW_JNI_PACKAGE"
echo " Current JNI method prefix: $CURRENT_JNI_METHOD_PREFIX"
echo " New JNI method prefix: $NEW_JNI_METHOD_PREFIX"
echo ""
echo "Important: For JNI methods, Java package components should NOT have '_1' between them."
echo " Instead of: Java_com_1android_1sshd_1server_1test006"
echo " Correct is: Java_com_android_sshd_server_test006"
echo " Only actual underscores in package names should be encoded as '_1'"
}
# JNI encoding converter function for underscore encoding in package names
convert_to_jni_encoding() {
local pkg=$1
local result=""
local IFS='.'
for part in $pkg; do
# Replace underscores with _1 (JNI encoding for underscore)
part="${part//_/_1}"
if [ -n "$result" ]; then
result="${result}_${part}"
else
result=$part
fi
done
echo $result
}
# Call the function to generate encodings
_generate_proper_jni_encodings
# UNIVERSAL JNI SIGNATURE FIXER
# This function will correctly fix all JNI signatures regardless of the current package name
# It can detect and fix any package name, even when it doesn't match the current package
_universal_jni_signature_fixer() {
local file=$1
local fixed=0
local any_package_fixed=0
echo "🔍 Universal JNI Signature Fixer analyzing: $file"
# First, update the FindClass reference for the expected current package
if grep -q "FindClass.*SimpleSSHDService" "$file"; then
sed -i "s|FindClass(env, \"[^\"]*SimpleSSHDService\")|FindClass(env, \"$NEW_JNI_CLASSPATH/SimpleSSHDService\")|g" "$file"
echo " ✅ Updated FindClass reference for SimpleSSHDService"
fi
# Update the CLASS definition if it exists
if grep -q "CLASS.*simplesshdservice" "$file"; then
sed -i "s|CLASS(simplesshdservice, \"[^\"]*\")|CLASS(simplesshdservice, \"$NEW_JNI_CLASSPATH/SimpleSSHDService\")|g" "$file"
echo " ✅ Updated CLASS definition for SimpleSSHDService"
fi
# The correct format for the new JNI method signature prefix
# Apply proper encoding for underscores in package names
local NEW_JNI_PKG=$(convert_to_jni_encoding "$PACKAGE_NAME")
NEW_JNI_PREFIX="Java_${NEW_JNI_PKG}"
# Get all JNI method declarations with SimpleSSHDService
local jni_methods=$(grep -o "Java_[a-zA-Z0-9_]*_SimpleSSHDService_[a-zA-Z0-9_]*" "$file" | sort -u || echo "")
if [ -z "$jni_methods" ]; then
echo " ️ No JNI method declarations found for SimpleSSHDService in $file"
else
echo " 🔍 Found JNI method declarations for SimpleSSHDService:"
echo "$jni_methods" | head -5
if [ "$(echo "$jni_methods" | wc -l)" -gt 5 ]; then
echo " ... and $(( $(echo "$jni_methods" | wc -l) - 5 )) more"
fi
# Extract all unique package prefixes from JNI signatures
local detected_prefixes=$(echo "$jni_methods" |
grep -o "Java_[a-zA-Z0-9_]*_SimpleSSHDService" |
sed 's/Java_\(.*\)_SimpleSSHDService/\1/' |
sort -u)
echo " 🔍 Detected package prefixes in JNI signatures:"
echo "$detected_prefixes" | sed 's/^/ /'
# For each detected package prefix, update it to the new package prefix
for pkg_prefix in $detected_prefixes; do
echo " 🔧 Processing package prefix: $pkg_prefix"
# Skip if this is already the correct package prefix
if [ "$pkg_prefix" = "$NEW_JNI_PKG" ]; then
echo " ✅ Package prefix already matches target: $pkg_prefix"
continue
fi
# Replace the package prefix in JNI function signatures
for method in $jni_methods; do
if [[ $method == Java_${pkg_prefix}_SimpleSSHDService* ]]; then
# Extract the method name without package prefix
local method_name=${method#*_SimpleSSHDService_}
# Create the new method signature with correct package
local new_method="${NEW_JNI_PREFIX}_SimpleSSHDService_${method_name}"
echo " 🔄 Replacing: $method$new_method"
# Replace all occurrences of this method in the file
sed -i "s/$method/$new_method/g" "$file"
fixed=$((fixed+1))
fi
done
any_package_fixed=$((any_package_fixed + fixed))
echo " ✅ Fixed $fixed JNI signatures with package prefix: $pkg_prefix"
done
fi
# Secondary, more aggressive approach using direct pattern matching for JNIEXPORT declarations
local jni_export_lines=$(grep -n "JNIEXPORT.*JNICALL.*SimpleSSHDService" "$file" || echo "")
if [ -n "$jni_export_lines" ]; then
echo " 🔍 Found JNIEXPORT declarations for SimpleSSHDService:"
echo "$jni_export_lines" | head -3
if [ "$(echo "$jni_export_lines" | wc -l)" -gt 3 ]; then
echo " ... and $(( $(echo "$jni_export_lines" | wc -l) - 3 )) more"
fi
# This pattern matches any Java_*_SimpleSSHDService pattern and replaces it with the correct new package prefix
sed -i -E "s/Java_[a-zA-Z0-9_]+_SimpleSSHDService/${NEW_JNI_PREFIX}_SimpleSSHDService/g" "$file"
echo " 🔧 Applied global signature pattern replacement"
# Count how many were replaced
local remaining=$(grep "JNIEXPORT.*JNICALL" "$file" | grep -v "${NEW_JNI_PREFIX}_SimpleSSHDService" | grep "SimpleSSHDService" || echo "")
if [ -z "$remaining" ]; then
echo " ✅ All JNI signatures updated successfully"
any_package_fixed=$((any_package_fixed + 1))
else
echo " ⚠️ Some JNI signatures still need manual review:"
echo "$remaining" | head -3
if [ "$(echo "$remaining" | wc -l)" -gt 3 ]; then
echo " ... and $(( $(echo "$remaining" | wc -l) - 3 )) more"
fi
# Create a backup of the file for safety
local backup_dir="./tmp_jni"
mkdir -p "$backup_dir"
cp "$file" "$backup_dir/$(basename "$file").bak.$(date +%Y%m%d%H%M%S)"
echo " ⚠️ Created backup of $file in $backup_dir"
# List the problematic JNI methods for manual fixing
echo " ❗ The following JNI methods need manual fixing:"
grep -n "JNIEXPORT.*JNICALL.*SimpleSSHDService" "$file" | grep -v "${NEW_JNI_PREFIX}_SimpleSSHDService" || echo " (none found on second check)"
fi
fi
# Verify string literals that may contain the package name
if grep -q "\"$CURRENT_PACKAGE\"" "$file" || grep -q "\"$CURRENT_PACKAGE\." "$file"; then
echo " 🔧 Updating package name string literals..."
sed -i "s|\"$CURRENT_PACKAGE\"|\"$PACKAGE_NAME\"|g" "$file"
sed -i "s|\"$CURRENT_PACKAGE\.|\"$PACKAGE_NAME.|g" "$file"
echo " ✅ Updated package name string literals"
fi
# Final verification
echo " 🔍 Final verification of JNI signatures in $file:"
grep -n "Java_.*_SimpleSSHDService" "$file" | head -5 || echo " (no JNI signatures found)"
echo ""
return $any_package_fixed
}
# Process all JNI files with the universal fixer
echo "🚀 Starting universal JNI signature fixing process..."
mkdir -p "./tmp_jni" # Create temp directory for backups
# First, find all C/C++ files in the JNI directory
JNI_FILES=$(find ./jni -type f \( -name "*.c" -o -name "*.cpp" -o -name "*.h" \))
if [ -z "$JNI_FILES" ]; then
echo "⚠️ WARNING: No JNI C/C++ files found in the ./jni directory"
else
echo "🔍 Found $(echo "$JNI_FILES" | wc -l) JNI files to process"
# First, process interface.c specifically if it exists
INTERFACE_FILE="./jni/interface.c"
if [ -f "$INTERFACE_FILE" ]; then
echo "🔧 Processing primary JNI file: $INTERFACE_FILE"
_universal_jni_signature_fixer "$INTERFACE_FILE"
INTERFACE_FIXED=$?
if [ $INTERFACE_FIXED -gt 0 ]; then
echo "✅ Successfully updated interface.c JNI signatures"
else
echo "️ No changes needed for interface.c JNI signatures"
fi
else
echo "⚠️ Warning: interface.c not found in ./jni directory"
fi
# Now process all other JNI files
for file in $JNI_FILES; do
# Skip interface.c as it was already processed
if [ "$file" != "$INTERFACE_FILE" ]; then
_universal_jni_signature_fixer "$file"
fi
done
fi
# Additional safety check - scan project for any hardcoded package references
echo ""
echo "🔍 Performing project-wide scan for hardcoded package references..."
HARDCODED_REFS=$(grep -r --include="*.{c,cpp,h,mk}" "$CURRENT_PACKAGE" ./jni ./app/src/main/jni 2>/dev/null || echo "")
if [ -n "$HARDCODED_REFS" ]; then
echo "⚠️ Found potential hardcoded package references:"
echo "$HARDCODED_REFS" | head -10
if [ "$(echo "$HARDCODED_REFS" | wc -l)" -gt 10 ]; then
echo "... and more"
fi
echo "🔧 Attempting to update hardcoded references..."
find ./jni ./app/src/main/jni -type f \( -name "*.c" -o -name "*.cpp" -o -name "*.h" -o -name "*.mk" \) -exec sed -i "s|$CURRENT_PACKAGE|$PACKAGE_NAME|g" {} \; 2>/dev/null || true
echo "✅ Updated hardcoded package references"
else
echo "✅ No additional hardcoded package references found"
fi
# Update intent filters in AndroidManifest.xml for specific actions
echo "Updating intent filters in AndroidManifest.xml..."
sed -i "s/<action android:name=\"$CURRENT_PACKAGE\.\(START\|STOP\)\"/<action android:name=\"$PACKAGE_NAME.\1\"/g" ./app/src/main/AndroidManifest.xml
echo "🔍 Checking for Android.mk files that might need updating..."
ANDROID_MK_FILES=$(find ./jni -name "Android.mk" 2>/dev/null || echo "")
if [ -n "$ANDROID_MK_FILES" ]; then
echo "📄 Found Android.mk files:"
echo "$ANDROID_MK_FILES"
# Update package references in Android.mk files
echo "🔧 Updating package references in Android.mk files..."
for mk_file in $ANDROID_MK_FILES; do
# Check if file contains the package name
if grep -q "$CURRENT_PACKAGE" "$mk_file"; then
echo " 📝 Updating: $mk_file"
sed -i "s|$CURRENT_PACKAGE|$PACKAGE_NAME|g" "$mk_file"
fi
done
fi
# ****************** REBUILD NATIVE LIBRARIES ******************
echo ""
echo "🔨 Rebuilding native libraries to match new package name..."
# Clean any previous build artifacts to ensure a fresh build
if [ -d "./obj" ]; then
echo "🧹 Cleaning previous build artifacts..."
rm -rf ./obj
fi
if [ -f "./jni/Android.mk" ]; then
echo "🏗️ Building native libraries using NDK..."
# Check if ndk-build is in PATH
if command -v ndk-build &> /dev/null; then
echo "📦 Running ndk-build..."
ndk-build -j4
if [ $? -eq 0 ]; then
echo "✅ Native libraries rebuilt successfully!"
# Check if libs directory exists and has files
if [ -d "./libs" ] && [ "$(ls -A ./libs 2>/dev/null)" ]; then
# Copy the built libraries to the app's lib directory
echo "📋 Copying rebuilt libraries to app/src/main/lib..."
mkdir -p ./app/src/main/lib
cp -rv ./libs/* ./app/src/main/lib/ 2>/dev/null || true
else
echo "⚠️ Warning: No libraries found in ./libs after build"
fi
else
echo "❌ Failed to rebuild native libraries!"
echo "⚠️ You will need to manually rebuild native code before using the app."
fi
else
echo "⚠️ Warning: ndk-build not found in PATH."
echo "⚠️ You will need to manually rebuild native code before using the app."
echo " Suggested command: <path-to-ndk>/ndk-build"
fi
else
echo "⚠️ Warning: No Android.mk found in ./jni"
echo "⚠️ You will need to manually rebuild native code before using the app."
fi
echo ""
echo "🎉 Package name update completed successfully!"
echo "The project has been updated from $CURRENT_PACKAGE to $PACKAGE_NAME"
echo "A backup of the original files was created in: $BACKUP_DIR"
echo ""
echo "JNI function signatures have been carefully updated to maintain compatibility."
echo "Native libraries have been rebuilt or instructions for manual rebuild provided."
echo ""
echo "Next steps:"
echo "1. Rebuild your project: ./scripts/full_build.sh"
echo "2. Install the new APK: adb install -r ./app/build/outputs/apk/release/app-release-aligned-debugSigned.apk"
echo "3. Launch the app: adb shell monkey -p $PACKAGE_NAME -c android.intent.category.LAUNCHER 1"
echo ""
echo "Note: External apps that reference this package will need to be updated manually."