feat: more restrictive android scripts, offline docs and plagiarization utils

This commit is contained in:
Krzysztof Rudnicki 2025-12-21 19:02:19 +01:00
parent 0977343332
commit 3193a19937
8 changed files with 1569 additions and 104 deletions

View File

@ -0,0 +1,121 @@
# Android Guardian - Blocked Apps List
# One package name per line
# Lines starting with # are comments
# ===== Food Delivery Apps =====
# Uber Eats
com.ubercab.eats
# Glovo
com.glovo
# Wolt
com.wolt.android
# Bolt Food
ee.mtakso.food
# Pyszne.pl / Takeaway
com.takeaway.android
com.pyszne.pl
# DoorDash
com.dd.doordash
# Grubhub
com.grubhub.android
# Deliveroo
com.deliveroo.orderapp
# Just Eat
com.justeat.app.uk
com.justeat.android
# Postmates
com.postmates.android
# Seamless
com.seamless.consumer
# Foodpanda
com.global.foodpanda.android
# ===== Browsers (to prevent bypassing blocks) =====
# Firefox
org.mozilla.firefox
org.mozilla.firefox_beta
org.mozilla.fenix
# Chrome (comment out if needed for some functionality)
# com.android.chrome
# Opera
com.opera.browser
com.opera.mini.native
com.opera.gx
# Brave
com.brave.browser
# Samsung Internet
com.sec.android.app.sbrowser
# Microsoft Edge
com.microsoft.emmx
# DuckDuckGo
com.duckduckgo.mobile.android
# Kiwi Browser
com.kiwibrowser.browser
# Vivaldi
com.vivaldi.browser
# UC Browser
com.UCMobile.intl
# Tor Browser
org.torproject.torbrowser
# ===== YouTube Apps =====
com.google.android.youtube
com.vanced.android.youtube
app.revanced.android.youtube
# ===== Fast Food Apps =====
# McDonald's
com.mcdonalds.app
com.mcdonalds.mobileapp
# KFC
com.yum.kfcpolska
com.kfc.app
# Burger King
com.emn8.mobilem8.nativeapp.bk
com.burgerking
# Pizza Hut
com.pizzahut.app
# Domino's
com.dominospizza
# Subway
com.subway.mobile
# ===== Other Distracting Apps =====
# TikTok
com.zhiliaoapp.musically
com.ss.android.ugc.trill
# Instagram (optional - comment out if needed)
# com.instagram.android
# Facebook (optional)
# com.facebook.katana
# Twitter/X
# com.twitter.android

View File

@ -0,0 +1,6 @@
id=android_guardian
name=Android Guardian (Hosts + App Blocker)
version=1.0
versionCode=1
author=linux-configuration
description=Persistent hosts blocking and app installation guard. Can only be controlled via ADB.

View File

@ -0,0 +1,9 @@
#!/system/bin/sh
# Runs early in boot - set up hosts file
# MODDIR is set by Magisk and points to this module's directory
GUARDIAN_DIR="/data/adb/android_guardian"
mkdir -p "$GUARDIAN_DIR"
# Log that we're starting
echo "[$(date '+%Y-%m-%d %H:%M:%S')] post-fs-data: Guardian module loading" >>"$GUARDIAN_DIR/guardian.log"

View File

@ -0,0 +1,77 @@
#!/system/bin/sh
# Android Guardian Service - runs at boot
# This service:
# 1. Monitors and protects the hosts file
# 2. Blocks installation of forbidden apps
# 3. Can only be stopped via ADB with the correct command
MODDIR=${0%/*}
GUARDIAN_DIR="/data/adb/android_guardian"
LOG_FILE="$GUARDIAN_DIR/guardian.log"
BLOCKED_APPS_FILE="$GUARDIAN_DIR/blocked_apps.txt"
CONTROL_FILE="$GUARDIAN_DIR/control"
HOSTS_BACKUP="$GUARDIAN_DIR/hosts.backup"
# Ensure guardian directory exists
mkdir -p "$GUARDIAN_DIR"
log() {
echo "[$(date '+%Y-%m-%d %H:%M:%S')] $*" >>"$LOG_FILE"
}
# Initialize control file if not exists
[ ! -f "$CONTROL_FILE" ] && echo "ENABLED" >"$CONTROL_FILE"
log "=== Android Guardian starting ==="
# Function to check if guardian is enabled
is_enabled() {
[ "$(cat "$CONTROL_FILE" 2>/dev/null)" = "ENABLED" ]
}
# Function to restore hosts file if tampered
protect_hosts() {
if [ -f "$HOSTS_BACKUP" ]; then
current_hash=$(md5sum /system/etc/hosts 2>/dev/null | cut -d' ' -f1)
backup_hash=$(md5sum "$HOSTS_BACKUP" 2>/dev/null | cut -d' ' -f1)
if [ "$current_hash" != "$backup_hash" ]; then
log "Hosts file tampering detected! Restoring..."
cp "$HOSTS_BACKUP" "$MODDIR/system/etc/hosts"
log "Hosts file restored"
fi
fi
}
# Function to uninstall blocked apps
check_blocked_apps() {
if [ ! -f "$BLOCKED_APPS_FILE" ]; then
return
fi
while IFS= read -r package || [ -n "$package" ]; do
# Skip comments and empty lines
case "$package" in
\#* | "") continue ;;
esac
# Check if package is installed
if pm list packages 2>/dev/null | grep -q "package:$package"; then
log "Blocked app detected: $package - Uninstalling..."
pm uninstall "$package" 2>/dev/null && log "Uninstalled: $package" || log "Failed to uninstall: $package"
fi
done <"$BLOCKED_APPS_FILE"
}
# Main monitoring loop
while true; do
if is_enabled; then
protect_hosts
check_blocked_apps
fi
# Check every 30 seconds
sleep 30
done &
log "Guardian service started (PID: $!)"

View File

@ -0,0 +1,16 @@
#!/system/bin/sh
# Cleanup when module is uninstalled
GUARDIAN_DIR="/data/adb/android_guardian"
# Only allow uninstall if control file says DISABLED
if [ -f "$GUARDIAN_DIR/control" ]; then
status=$(cat "$GUARDIAN_DIR/control")
if [ "$status" != "DISABLED" ]; then
echo "Guardian is still enabled! Use ADB to disable first:"
echo " adb shell 'echo DISABLED > /data/adb/android_guardian/control'"
exit 1
fi
fi
# Clean up guardian data
rm -rf "$GUARDIAN_DIR"

View File

@ -0,0 +1,228 @@
#!/usr/bin/env bash
# Install Zeal - Offline Documentation Browser
# Downloads official documentation for: C, C++, JavaScript, TypeScript, Python
#
# Zeal is a free, open source (GPL) offline documentation browser
# Similar to Dash for macOS, uses compatible docsets
set -euo pipefail
# Colors for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m'
success() { echo -e "${GREEN}$1${NC}"; }
warn() { echo -e "${YELLOW}$1${NC}"; }
error() { echo -e "${RED}$1${NC}"; }
info() { echo -e "${BLUE} $1${NC}"; }
echo "=============================================="
echo " Offline Documentation Installer"
echo " Languages: C, C++, JavaScript, TypeScript, Python"
echo "=============================================="
echo ""
# Detect package manager and install Zeal
install_zeal() {
if command -v zeal &>/dev/null; then
success "Zeal is already installed"
return 0
fi
echo "Installing Zeal offline documentation browser..."
if command -v pacman &>/dev/null; then
# Arch Linux
sudo pacman -S --noconfirm zeal
elif command -v apt &>/dev/null; then
# Debian/Ubuntu
sudo apt update
sudo apt install -y zeal
elif command -v dnf &>/dev/null; then
# Fedora
sudo dnf install -y zeal
elif command -v zypper &>/dev/null; then
# openSUSE
sudo zypper install -y zeal
elif command -v flatpak &>/dev/null; then
# Flatpak fallback
flatpak install -y flathub org.zealdocs.Zeal
else
error "Could not detect package manager. Please install Zeal manually:"
echo " https://zealdocs.org/download.html"
return 1
fi
success "Zeal installed successfully"
}
# Get Zeal docsets directory
get_docsets_dir() {
local docsets_dir
# Check if using Flatpak
if command -v flatpak &>/dev/null && flatpak list | grep -q "org.zealdocs.Zeal"; then
docsets_dir="$HOME/.var/app/org.zealdocs.Zeal/data/Zeal/Zeal/docsets"
else
# Standard installation
docsets_dir="$HOME/.local/share/Zeal/Zeal/docsets"
fi
mkdir -p "$docsets_dir"
echo "$docsets_dir"
}
# Download a docset from Zeal feeds
download_docset() {
local name="$1"
local docsets_dir="$2"
# Check if already installed
if [ -d "$docsets_dir/${name}.docset" ]; then
warn "$name docset already installed"
return 0
fi
info "Downloading $name documentation..."
# Use Zeal's built-in feed system via CLI or direct download
# Zeal stores docsets in .docset directories
# Try to get from dash-user-contributions or official feeds
local download_url=""
case "$name" in
"C")
download_url="http://kapeli.com/feeds/C.tgz"
;;
"C++")
download_url="http://kapeli.com/feeds/C%2B%2B.tgz"
;;
"JavaScript")
download_url="http://kapeli.com/feeds/JavaScript.tgz"
;;
"TypeScript")
download_url="http://kapeli.com/feeds/TypeScript.tgz"
;;
"Python_3")
download_url="http://kapeli.com/feeds/Python_3.tgz"
;;
"Python_2")
download_url="http://kapeli.com/feeds/Python_2.tgz"
;;
"Bash")
download_url="http://kapeli.com/feeds/Bash.tgz"
;;
"HTML")
download_url="http://kapeli.com/feeds/HTML.tgz"
;;
"CSS")
download_url="http://kapeli.com/feeds/CSS.tgz"
;;
"NodeJS")
download_url="http://kapeli.com/feeds/NodeJS.tgz"
;;
"React")
download_url="http://kapeli.com/feeds/React.tgz"
;;
*)
warn "Unknown docset: $name"
return 1
;;
esac
# Download and extract
local temp_file
temp_file=$(mktemp)
echo " URL: $download_url"
if curl -fL --progress-bar "$download_url" -o "$temp_file"; then
echo " Extracting to $docsets_dir..."
tar -xzf "$temp_file" -C "$docsets_dir"
rm -f "$temp_file"
success "$name documentation downloaded"
else
rm -f "$temp_file"
warn "Failed to download $name - you can install it from Zeal's UI"
return 1
fi
}
# Main installation
main() {
# Step 1: Install Zeal
echo ""
echo "=== Step 1: Installing Zeal ==="
install_zeal || exit 1
# Step 2: Get docsets directory
echo ""
echo "=== Step 2: Preparing docsets directory ==="
local docsets_dir
docsets_dir=$(get_docsets_dir)
success "Docsets directory: $docsets_dir"
# Step 3: Download requested docsets
echo ""
echo "=== Step 3: Downloading Documentation ==="
echo ""
# Core requested languages
local docsets=("C" "C++" "JavaScript" "TypeScript" "Python_3")
# Optional extras (comment out if not needed)
local extras=("Bash" "HTML" "CSS" "NodeJS")
# Download core docsets
for docset in "${docsets[@]}"; do
download_docset "$docset" "$docsets_dir"
done
# Ask about extras
echo ""
read -r -p "Install additional docsets (Bash, HTML, CSS, NodeJS)? [Y/n] " response
if [[ ! "$response" =~ ^[Nn]$ ]]; then
for docset in "${extras[@]}"; do
download_docset "$docset" "$docsets_dir"
done
fi
# Summary
echo ""
echo "=============================================="
echo " Installation Complete!"
echo "=============================================="
echo ""
echo "Installed documentation:"
for f in "$docsets_dir"/*.docset; do
if [[ -d "$f" ]]; then
echo "$(basename "$f" .docset)"
fi
done
echo ""
echo "Usage:"
echo " Launch Zeal from your application menu, or run: zeal"
echo ""
echo "To download additional docsets:"
echo " 1. Open Zeal"
echo " 2. Go to Tools → Docsets"
echo " 3. Click 'Available' tab and download what you need"
echo ""
echo "Keyboard shortcut tip:"
echo " Set a global hotkey in Zeal → Preferences → Global Shortcuts"
echo " (e.g., Alt+Space for quick documentation lookup)"
echo ""
echo "=============================================="
# Offer to launch Zeal
read -r -p "Launch Zeal now? [y/N] " response
if [[ "$response" =~ ^[Yy]$ ]]; then
nohup zeal &>/dev/null &
success "Zeal launched"
fi
}
main "$@"

View File

@ -0,0 +1,532 @@
#!/usr/bin/env bash
# Install Free & Open Source Plagiarism Detection Tools for Text
# Suitable for academic work (theses, papers, etc.)
#
# Tools installed:
# 1. Python NLP-based similarity detection (sklearn, NLTK, spaCy)
# 2. Sherlock text plagiarism detector
# 3. Ferret (Java-based, if Java available)
# 4. Optional: WCopyfind via Wine (Windows tool)
set -euo pipefail
INSTALL_DIR="${HOME}/.local/share/plagiarism-tools"
VENV_DIR="${HOME}/.local/share/plagiarism-venv"
echo "=============================================="
echo " Open Source Plagiarism Detection Installer"
echo " For Academic Text (Theses, Papers, etc.)"
echo "=============================================="
echo ""
# Colors for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m' # No Color
success() { echo -e "${GREEN}$1${NC}"; }
warn() { echo -e "${YELLOW}$1${NC}"; }
error() { echo -e "${RED}$1${NC}"; }
# Create installation directory
mkdir -p "$INSTALL_DIR"
# ------------------------------------------------------------------------------
# 1. Python-based NLP Plagiarism Detection Environment
# ------------------------------------------------------------------------------
echo ""
echo "=== 1. Installing Python NLP-based Plagiarism Tools ==="
# Check for Python 3
if ! command -v python3 &>/dev/null; then
error "Python 3 is required but not installed."
exit 1
fi
# Create virtual environment
if [ ! -d "$VENV_DIR" ]; then
echo "Creating Python virtual environment..."
python3 -m venv "$VENV_DIR"
success "Virtual environment created at $VENV_DIR"
else
warn "Virtual environment already exists at $VENV_DIR"
fi
# Activate and install packages
source "$VENV_DIR/bin/activate"
echo "Installing Python packages for text similarity detection..."
pip install --upgrade pip
pip install --progress-bar on \
scikit-learn \
nltk \
spacy \
gensim \
numpy \
pandas \
python-docx \
PyPDF2 \
beautifulsoup4 \
lxml \
textdistance \
fuzzywuzzy \
python-Levenshtein
success "Python NLP packages installed"
# Download NLTK data
echo "Downloading NLTK data (stopwords, punkt tokenizer)..."
python3 -c "
import nltk
nltk.download('punkt')
nltk.download('stopwords')
nltk.download('punkt_tab')
nltk.download('averaged_perceptron_tagger')
nltk.download('wordnet')
"
success "NLTK data downloaded"
# Download spaCy English model (small)
echo "Downloading spaCy English model..."
python3 -m spacy download en_core_web_sm 2>/dev/null || warn "spaCy model download may need manual install: python -m spacy download en_core_web_sm"
success "spaCy model installed"
# Create a simple plagiarism checker script
cat >"$INSTALL_DIR/check_plagiarism.py" <<'PYEOF'
#!/usr/bin/env python3
"""
Simple Text Plagiarism Checker
Compares documents using multiple similarity algorithms.
Usage:
python check_plagiarism.py file1.txt file2.txt [file3.txt ...]
python check_plagiarism.py --dir /path/to/documents/
"""
import argparse
import os
import sys
from pathlib import Path
from typing import List, Tuple
import numpy as np
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.metrics.pairwise import cosine_similarity
import nltk
from nltk.corpus import stopwords
from nltk.tokenize import word_tokenize, sent_tokenize
# Ensure NLTK data is available
try:
stopwords.words('english')
except LookupError:
nltk.download('stopwords', quiet=True)
nltk.download('punkt', quiet=True)
def read_file(filepath: str) -> str:
"""Read text from various file formats."""
path = Path(filepath)
suffix = path.suffix.lower()
if suffix == '.pdf':
try:
from PyPDF2 import PdfReader
reader = PdfReader(filepath)
return ' '.join(page.extract_text() or '' for page in reader.pages)
except ImportError:
print("Warning: PyPDF2 not installed, cannot read PDF files")
return ""
elif suffix == '.docx':
try:
from docx import Document
doc = Document(filepath)
return ' '.join(para.text for para in doc.paragraphs)
except ImportError:
print("Warning: python-docx not installed, cannot read DOCX files")
return ""
else:
# Assume plain text
with open(filepath, 'r', encoding='utf-8', errors='ignore') as f:
return f.read()
def preprocess_text(text: str) -> str:
"""Clean and preprocess text for comparison."""
# Lowercase
text = text.lower()
# Tokenize and remove stopwords
try:
stop_words = set(stopwords.words('english'))
words = word_tokenize(text)
words = [w for w in words if w.isalnum() and w not in stop_words]
return ' '.join(words)
except Exception:
# Fallback: simple preprocessing
return ' '.join(text.split())
def compute_similarity_matrix(documents: List[str]) -> np.ndarray:
"""Compute TF-IDF cosine similarity matrix."""
vectorizer = TfidfVectorizer(
ngram_range=(1, 3), # Use unigrams, bigrams, trigrams
min_df=1,
max_df=0.95
)
tfidf_matrix = vectorizer.fit_transform(documents)
return cosine_similarity(tfidf_matrix)
def find_similar_passages(text1: str, text2: str, min_words: int = 5) -> List[Tuple[str, str, float]]:
"""Find similar sentence-level passages between two texts."""
sentences1 = sent_tokenize(text1)
sentences2 = sent_tokenize(text2)
if not sentences1 or not sentences2:
return []
# Filter short sentences
sentences1 = [s for s in sentences1 if len(s.split()) >= min_words]
sentences2 = [s for s in sentences2 if len(s.split()) >= min_words]
if not sentences1 or not sentences2:
return []
all_sentences = sentences1 + sentences2
preprocessed = [preprocess_text(s) for s in all_sentences]
try:
vectorizer = TfidfVectorizer(ngram_range=(1, 2))
tfidf_matrix = vectorizer.fit_transform(preprocessed)
except ValueError:
return []
n1 = len(sentences1)
similarities = []
for i, s1 in enumerate(sentences1):
for j, s2 in enumerate(sentences2):
sim = cosine_similarity(
tfidf_matrix[i:i+1],
tfidf_matrix[n1+j:n1+j+1]
)[0][0]
if sim > 0.5: # Threshold for suspicious similarity
similarities.append((s1, s2, sim))
return sorted(similarities, key=lambda x: x[2], reverse=True)
def main():
parser = argparse.ArgumentParser(
description='Text Plagiarism Checker - Compare documents for similarity'
)
parser.add_argument('files', nargs='*', help='Files to compare')
parser.add_argument('--dir', '-d', help='Directory containing documents to compare')
parser.add_argument('--threshold', '-t', type=float, default=0.3,
help='Similarity threshold for flagging (0-1, default: 0.3)')
parser.add_argument('--detailed', '-v', action='store_true',
help='Show detailed similar passages')
args = parser.parse_args()
# Collect files
files = []
if args.files:
files.extend(args.files)
if args.dir:
dir_path = Path(args.dir)
for ext in ['*.txt', '*.pdf', '*.docx', '*.md', '*.tex']:
files.extend(str(f) for f in dir_path.glob(ext))
if len(files) < 2:
print("Error: Need at least 2 files to compare")
parser.print_help()
sys.exit(1)
print(f"\n{'='*60}")
print(f" Plagiarism Check - Analyzing {len(files)} documents")
print(f"{'='*60}\n")
# Read and preprocess documents
documents = []
filenames = []
for f in files:
if os.path.exists(f):
text = read_file(f)
if text.strip():
documents.append(preprocess_text(text))
filenames.append(os.path.basename(f))
else:
print(f"Warning: {f} is empty or unreadable")
else:
print(f"Warning: {f} does not exist")
if len(documents) < 2:
print("Error: Not enough valid documents to compare")
sys.exit(1)
# Compute similarity
print("Computing document similarities...\n")
sim_matrix = compute_similarity_matrix(documents)
# Report results
print(f"{'Document Pair':<50} {'Similarity':>12}")
print("-" * 62)
suspicious_pairs = []
for i in range(len(documents)):
for j in range(i + 1, len(documents)):
similarity = sim_matrix[i][j]
pair_name = f"{filenames[i]} <-> {filenames[j]}"
if similarity >= args.threshold:
suspicious_pairs.append((i, j, similarity, pair_name))
print(f"{pair_name:<50} {similarity:>10.1%} ⚠️")
else:
print(f"{pair_name:<50} {similarity:>10.1%}")
print("-" * 62)
# Summary
if suspicious_pairs:
print(f"\n⚠ {len(suspicious_pairs)} pair(s) exceed {args.threshold:.0%} similarity threshold\n")
if args.detailed:
print("\n" + "="*60)
print(" Detailed Similar Passages")
print("="*60)
for i, j, sim, pair_name in suspicious_pairs[:3]: # Limit to top 3
print(f"\n{pair_name} ({sim:.1%} similar):")
print("-" * 40)
raw_docs = [read_file(files[i]), read_file(files[j])]
passages = find_similar_passages(raw_docs[0], raw_docs[1])
for s1, s2, psim in passages[:5]: # Top 5 passages
print(f"\n[{psim:.0%}] Document 1: \"{s1[:100]}...\"")
print(f" Document 2: \"{s2[:100]}...\"")
else:
print(f"\n✓ No document pairs exceed {args.threshold:.0%} similarity threshold")
print("\n" + "="*60)
print(" Analysis complete")
print("="*60 + "\n")
if __name__ == '__main__':
main()
PYEOF
chmod +x "$INSTALL_DIR/check_plagiarism.py"
success "Created plagiarism checker script at $INSTALL_DIR/check_plagiarism.py"
# Create convenience wrapper
mkdir -p "$HOME/.local/bin"
cat >"$HOME/.local/bin/plagcheck" <<WRAPEOF
#!/usr/bin/env bash
# Wrapper for plagiarism checker
source "$VENV_DIR/bin/activate"
python "$INSTALL_DIR/check_plagiarism.py" "\$@"
WRAPEOF
chmod +x "$HOME/.local/bin/plagcheck"
success "Created 'plagcheck' command in ~/.local/bin/"
deactivate
# ------------------------------------------------------------------------------
# 2. Sherlock for Text (Clone from GitHub)
# ------------------------------------------------------------------------------
echo ""
echo "=== 2. Installing Sherlock Text Plagiarism Detector ==="
SHERLOCK_DIR="$INSTALL_DIR/sherlock"
if [ ! -d "$SHERLOCK_DIR" ]; then
# There are several Sherlock implementations; using a popular Python one
if command -v git &>/dev/null; then
# Clone a text-based similarity tool
git clone --depth 1 https://github.com/Zedeldi/sherlock-py.git "$SHERLOCK_DIR" 2>/dev/null || {
warn "Could not clone sherlock-py, trying alternative..."
# Alternative: Create a simple n-gram based sherlock
mkdir -p "$SHERLOCK_DIR"
cat >"$SHERLOCK_DIR/sherlock.py" <<'SHERLOCKEOF'
#!/usr/bin/env python3
"""
Sherlock - Simple text plagiarism detector using n-gram fingerprinting.
Based on the original Sherlock algorithm.
"""
import argparse
import hashlib
import os
import sys
from collections import defaultdict
from pathlib import Path
def tokenize(text: str) -> list:
"""Simple word tokenization."""
return [w.lower() for w in text.split() if w.isalnum()]
def get_ngrams(tokens: list, n: int = 3) -> list:
"""Generate n-grams from token list."""
return [tuple(tokens[i:i+n]) for i in range(len(tokens) - n + 1)]
def fingerprint(text: str, ngram_size: int = 3, sample_rate: int = 4) -> set:
"""Create document fingerprint using sampled n-gram hashes."""
tokens = tokenize(text)
ngrams = get_ngrams(tokens, ngram_size)
fingerprints = set()
for i, ng in enumerate(ngrams):
if i % sample_rate == 0: # Sample every nth n-gram
h = hashlib.md5(''.join(ng).encode()).hexdigest()[:8]
fingerprints.add(h)
return fingerprints
def compare_documents(fp1: set, fp2: set) -> float:
"""Jaccard similarity between fingerprints."""
if not fp1 or not fp2:
return 0.0
intersection = len(fp1 & fp2)
union = len(fp1 | fp2)
return intersection / union if union > 0 else 0.0
def read_document(filepath: str) -> str:
"""Read document content."""
with open(filepath, 'r', encoding='utf-8', errors='ignore') as f:
return f.read()
def main():
parser = argparse.ArgumentParser(description='Sherlock - Text Plagiarism Detector')
parser.add_argument('files', nargs='+', help='Files to compare')
parser.add_argument('--ngram', '-n', type=int, default=3, help='N-gram size (default: 3)')
parser.add_argument('--threshold', '-t', type=float, default=0.1, help='Similarity threshold')
args = parser.parse_args()
if len(args.files) < 2:
print("Need at least 2 files to compare")
sys.exit(1)
# Read and fingerprint documents
docs = {}
for f in args.files:
if os.path.exists(f):
text = read_document(f)
docs[f] = fingerprint(text, args.ngram)
print(f"\nSherlock Plagiarism Analysis")
print("=" * 50)
# Compare all pairs
files = list(docs.keys())
for i in range(len(files)):
for j in range(i + 1, len(files)):
sim = compare_documents(docs[files[i]], docs[files[j]])
name1 = os.path.basename(files[i])
name2 = os.path.basename(files[j])
flag = " ⚠️ SUSPICIOUS" if sim >= args.threshold else ""
print(f"{name1} <-> {name2}: {sim:.1%}{flag}")
print("=" * 50)
if __name__ == '__main__':
main()
SHERLOCKEOF
chmod +x "$SHERLOCK_DIR/sherlock.py"
}
success "Sherlock installed at $SHERLOCK_DIR"
else
warn "Git not available, skipping Sherlock installation"
fi
else
warn "Sherlock already installed at $SHERLOCK_DIR"
fi
# ------------------------------------------------------------------------------
# 3. Ferret (Java-based) - Optional
# ------------------------------------------------------------------------------
echo ""
echo "=== 3. Checking for Ferret (Java-based plagiarism tool) ==="
if command -v java &>/dev/null; then
FERRET_DIR="$INSTALL_DIR/ferret"
if [ ! -d "$FERRET_DIR" ]; then
mkdir -p "$FERRET_DIR"
echo "Ferret is a Java-based tool from University of Hertfordshire."
echo "Download manually from: https://homepages.herts.ac.uk/~comqcln/Ferret/"
echo "Place JAR file in: $FERRET_DIR"
warn "Ferret requires manual download (academic license)"
fi
else
warn "Java not installed, skipping Ferret"
fi
# ------------------------------------------------------------------------------
# 4. WCopyfind via Wine (Optional)
# ------------------------------------------------------------------------------
echo ""
echo "=== 4. WCopyfind Information (Windows tool, needs Wine) ==="
if command -v wine &>/dev/null; then
echo "Wine is available. WCopyfind can be run via Wine."
echo "Download from: https://plagiarism.bloomfieldmedia.com/software/wcopyfind/"
echo "Run with: wine /path/to/WCopyfind.exe"
warn "WCopyfind requires manual download"
else
echo "Wine not installed. To use WCopyfind:"
echo " 1. Install wine: sudo apt install wine (or equivalent)"
echo " 2. Download WCopyfind from: https://plagiarism.bloomfieldmedia.com/software/wcopyfind/"
warn "WCopyfind skipped (Wine not available)"
fi
# ------------------------------------------------------------------------------
# Summary
# ------------------------------------------------------------------------------
echo ""
echo "=============================================="
echo " Installation Complete!"
echo "=============================================="
echo ""
echo "Installed tools:"
echo ""
echo "1. Python NLP Plagiarism Checker (TF-IDF, cosine similarity)"
echo " Usage: plagcheck file1.txt file2.txt"
echo " plagcheck --dir /path/to/documents/ --detailed"
echo " Location: $INSTALL_DIR/check_plagiarism.py"
echo ""
echo "2. Sherlock (n-gram fingerprinting)"
echo " Location: $SHERLOCK_DIR/sherlock.py"
echo ""
echo "3. Python virtual environment with NLP libraries:"
echo " - scikit-learn (TF-IDF, cosine similarity)"
echo " - NLTK (tokenization, stopwords)"
echo " - spaCy (NLP processing)"
echo " - gensim (document similarity)"
echo " - textdistance, fuzzywuzzy (string matching)"
echo " Activate with: source $VENV_DIR/bin/activate"
echo ""
echo "Quick Start:"
echo " plagcheck thesis_v1.pdf thesis_v2.pdf --detailed"
echo " plagcheck --dir ./student_papers/ --threshold 0.4"
echo ""
echo "Note: Ensure ~/.local/bin is in your PATH:"
echo ' export PATH="$HOME/.local/bin:$PATH"'
echo ""
echo "=============================================="
# Add to PATH reminder
if [[ ":$PATH:" != *":$HOME/.local/bin:"* ]]; then
warn "Add ~/.local/bin to your PATH by adding this to ~/.bashrc or ~/.zshrc:"
echo ' export PATH="$HOME/.local/bin:$PATH"'
fi

View File

@ -1,5 +1,6 @@
#!/bin/bash
# update_android_hosts.sh - Update Android hosts file from Linux config
# update_android_hosts.sh - Deploy Android Guardian (hosts blocking + app blocker)
# This creates a persistent protection that can ONLY be controlled via ADB
set -euo pipefail
# Source common library
@ -9,51 +10,315 @@ source "$SCRIPT_DIR/../lib/common.sh"
# shellcheck source=../lib/android.sh
source "$SCRIPT_DIR/../lib/android.sh"
# Initialize Android script (handles sudo, sets WORK_DIR)
init_android_script "$@"
GUARDIAN_MODULE_DIR="$SCRIPT_DIR/android_guardian"
GUARDIAN_DATA_DIR="/data/adb/android_guardian"
MODULE_DEST="/data/adb/modules/android_guardian"
log "Updating Android hosts file from Linux configuration..."
# Ensure android-tools (adb) is installed
ensure_adb_installed() {
if command -v adb &>/dev/null; then
return 0
fi
log "adb not found, installing android-tools..."
if command -v pacman &>/dev/null; then
sudo pacman -S --noconfirm android-tools || die "Failed to install android-tools"
elif command -v apt-get &>/dev/null; then
sudo apt-get update && sudo apt-get install -y adb || die "Failed to install adb"
elif command -v dnf &>/dev/null; then
sudo dnf install -y android-tools || die "Failed to install android-tools"
else
die "adb not found and could not determine package manager. Please install android-tools manually."
fi
# Verify installation
if ! command -v adb &>/dev/null; then
die "adb installation failed"
fi
log "android-tools installed successfully"
}
show_usage() {
cat <<EOF
Usage: $(basename "$0") [COMMAND]
Commands:
install Install/update Android Guardian module (default)
status Show guardian status
disable Temporarily disable guardian (requires ADB)
enable Re-enable guardian (requires ADB)
uninstall Remove guardian module (requires ADB + disable first)
logs Show guardian logs
block-app Add an app to block list
unblock-app Remove an app from block list
list-blocked Show blocked apps list
pair Pair with device over WiFi (Android 11+, no USB needed)
connect Connect to already-paired device over WiFi
disconnect Disconnect wireless ADB
Android Guardian provides:
- Persistent hosts-based ad/tracker blocking
- Automatic uninstallation of forbidden apps (browsers, food delivery, etc.)
- Protection that can ONLY be controlled via ADB connection
The module CANNOT be disabled from the Magisk app on the phone.
You MUST connect the phone to a PC and use this script to control it.
Wireless Setup (Android 11+):
1. On phone: Settings > Developer Options > Wireless debugging > Enable
2. Tap "Pair device with pairing code" to get IP:port and code
3. Run: $0 pair
4. Future connections: $0 connect
EOF
}
# Wireless ADB connection file
WIRELESS_CONFIG="$HOME/.config/android_guardian_wireless"
# Discover Android devices on the network using mDNS
discover_android_device() {
local found_address=""
# Ensure avahi-browse is available
if ! command -v avahi-browse &>/dev/null; then
if command -v pacman &>/dev/null; then
echo "Installing avahi for device discovery..." >&2
sudo pacman -S --noconfirm avahi nss-mdns &>/dev/null || true
sudo systemctl enable --now avahi-daemon &>/dev/null || true
elif command -v apt-get &>/dev/null; then
sudo apt-get install -y avahi-utils &>/dev/null || true
fi
fi
if command -v avahi-browse &>/dev/null; then
echo "Scanning for Android devices (5 seconds)..." >&2
# Android wireless debugging advertises as _adb-tls-connect._tcp
local discovery_result
discovery_result=$(timeout 5 avahi-browse -rpt _adb-tls-connect._tcp 2>/dev/null | grep "^=" | head -1)
if [[ -n "$discovery_result" ]]; then
# Parse: =;eth0;IPv4;adb-...;_adb-tls-connect._tcp;local;hostname.local;192.168.x.x;port;...
local ip port
ip=$(echo "$discovery_result" | cut -d';' -f8)
port=$(echo "$discovery_result" | cut -d';' -f9)
if [[ -n "$ip" && -n "$port" ]]; then
found_address="$ip:$port"
echo "✓ Found device: $found_address" >&2
fi
fi
fi
# Fallback: try adb's mdns discovery
if [[ -z "$found_address" ]]; then
echo "Trying adb mdns discovery..." >&2
# adb can discover devices via mdns
local mdns_result
mdns_result=$(timeout 5 adb mdns services 2>/dev/null | grep -E "adb-tls-connect|_adb\._tcp" | head -1)
if [[ -n "$mdns_result" ]]; then
# Try to extract IP:port from the result
local service_name
service_name=$(echo "$mdns_result" | awk '{print $1}')
if [[ -n "$service_name" ]]; then
# Try connecting via service name
echo "Found service: $service_name" >&2
fi
fi
fi
# Return found address (or empty)
echo "$found_address"
}
# Pair with device over WiFi (Android 11+)
cmd_pair() {
ensure_adb_installed
echo ""
echo "=== Wireless ADB Pairing (Android 11+) ==="
echo ""
echo "On your phone:"
echo " 1. Go to Settings > Developer Options > Wireless debugging"
echo " 2. Enable Wireless debugging"
echo " 3. Tap 'Pair device with pairing code'"
echo " 4. Note the IP:port and pairing code shown"
echo ""
read -rp "Enter pairing IP:port (e.g., 192.168.1.100:37123): " pair_address
read -rp "Enter pairing code: " pair_code
if [[ -z "$pair_address" || -z "$pair_code" ]]; then
die "Pairing address and code are required"
fi
log "Pairing with device at $pair_address..."
if adb pair "$pair_address" "$pair_code"; then
echo ""
echo "✓ Pairing successful!"
echo ""
echo "Now get the connection address:"
echo " On phone: Wireless debugging screen shows IP:port under 'IP address & Port'"
echo " (This is DIFFERENT from the pairing port)"
echo ""
read -rp "Enter connection IP:port (e.g., 192.168.1.100:41567): " connect_address
if [[ -n "$connect_address" ]]; then
# Save for future connections
mkdir -p "$(dirname "$WIRELESS_CONFIG")"
echo "$connect_address" >"$WIRELESS_CONFIG"
log "Saved connection address for future use"
# Connect now
cmd_connect
fi
else
die "Pairing failed. Make sure the code is correct and you're on the same network."
fi
}
# Connect to already-paired device
cmd_connect() {
ensure_adb_installed
local connect_address=""
# Check for saved address
if [[ -f "$WIRELESS_CONFIG" ]]; then
connect_address=$(cat "$WIRELESS_CONFIG")
log "Using saved address: $connect_address"
fi
# Try auto-discovery if no saved address
if [[ -z "$connect_address" ]]; then
echo ""
log "Searching for Android devices on network..."
connect_address=$(discover_android_device)
fi
# Manual fallback
if [[ -z "$connect_address" ]]; then
echo ""
echo "Auto-discovery failed. Enter address manually."
echo "On phone: Settings > Developer Options > Wireless debugging"
echo "Look for IP address & Port (NOT the pairing port)"
echo ""
read -rp "Enter connection IP:port (e.g., 192.168.1.100:41567): " connect_address
if [[ -z "$connect_address" ]]; then
die "Connection address is required"
fi
fi
# Save for future
mkdir -p "$(dirname "$WIRELESS_CONFIG")"
echo "$connect_address" >"$WIRELESS_CONFIG"
log "Connecting to $connect_address..."
if adb connect "$connect_address" | grep -q "connected"; then
echo ""
echo "✓ Connected to device wirelessly!"
echo ""
# Verify connection
if adb devices | grep -q "$connect_address"; then
echo "Device ready. You can now run other commands."
fi
else
echo ""
echo "Connection failed. Possible issues:"
echo " - Wireless debugging not enabled on phone"
echo " - Phone and PC not on same WiFi network"
echo " - Port changed (check Wireless debugging screen)"
echo " - May need to pair first: $0 pair"
echo ""
# Clear saved config since it failed
rm -f "$WIRELESS_CONFIG"
exit 1
fi
}
# Disconnect wireless ADB
cmd_disconnect() {
ensure_adb_installed
log "Disconnecting all wireless devices..."
adb disconnect
echo "✓ Disconnected"
}
# Check device connection and root
ensure_device_ready() {
ensure_adb_installed
# Check if any device is connected
if ! adb devices | grep -qE "device$|:.*device$"; then
echo ""
echo "No device connected!"
echo ""
echo "Options:"
echo " 1. Connect USB cable with debugging enabled"
echo " 2. Use wireless: $0 pair (first time) or $0 connect"
echo ""
# Check if we have a saved wireless config
if [[ -f "$WIRELESS_CONFIG" ]]; then
read -rp "Try connecting to saved wireless device? [Y/n]: " try_wireless
if [[ "${try_wireless,,}" != "n" ]]; then
cmd_connect
else
exit 1
fi
else
exit 1
fi
fi
# Check device connection
check_adb_device
# Check root access
check_adb_root
}
# Use the StevenBlack cache or /etc/hosts
HOSTS_FILE="$WORK_DIR/hosts"
# Build the module zip
build_module() {
local tmp_dir="$WORK_DIR/guardian_module"
local module_zip="$WORK_DIR/android_guardian.zip"
echo "[BUILD] Building Android Guardian module..." >&2
rm -rf "$tmp_dir"
mkdir -p "$tmp_dir/system/etc"
# Copy module files
cp "$GUARDIAN_MODULE_DIR/module.prop" "$tmp_dir/"
cp "$GUARDIAN_MODULE_DIR/service.sh" "$tmp_dir/"
cp "$GUARDIAN_MODULE_DIR/post-fs-data.sh" "$tmp_dir/"
cp "$GUARDIAN_MODULE_DIR/uninstall.sh" "$tmp_dir/"
# Build hosts file
local hosts_file="$tmp_dir/system/etc/hosts"
if [[ -f /etc/hosts.stevenblack ]]; then
log "Using StevenBlack hosts cache..."
cp /etc/hosts.stevenblack "$HOSTS_FILE"
echo "[BUILD] Using StevenBlack hosts cache..." >&2
cp /etc/hosts.stevenblack "$hosts_file"
elif [[ -f /etc/hosts ]]; then
log "Using /etc/hosts..."
cp /etc/hosts "$HOSTS_FILE"
echo "[BUILD] Using /etc/hosts..." >&2
cp /etc/hosts "$hosts_file"
else
die "No hosts file found"
fi
# Show stats
TOTAL_ENTRIES=$(grep -c "^0\.0\.0\.0 " "$HOSTS_FILE" || echo 0)
log "Hosts file contains $TOTAL_ENTRIES blocked domains"
# Push to device
log "Pushing hosts file to device..."
adb push "$HOSTS_FILE" /sdcard/hosts || die "Failed to push hosts file"
# Install systemlessly
log "Updating systemless hosts..."
adb shell "su -c 'mkdir -p /data/adb/modules/systemless_hosts/system/etc'" || die "Failed to create module directory"
adb shell "su -c 'cp /sdcard/hosts /data/adb/modules/systemless_hosts/system/etc/hosts'" || die "Failed to install hosts file"
adb shell "su -c 'chmod 644 /data/adb/modules/systemless_hosts/system/etc/hosts'" || die "Failed to set permissions"
adb shell "su -c 'rm /sdcard/hosts'"
echo "[$(date +'%Y-%m-%d %H:%M:%S%z')] ✓ Hosts file updated successfully"
# Append custom blocking entries
echo "[$(date +'%Y-%m-%d %H:%M:%S%z')] Adding custom blocking entries..."
adb shell "su -c 'cat >> /data/adb/modules/systemless_hosts/system/etc/hosts << \"CUSTOM_EOF\"
cat >>"$hosts_file" <<'CUSTOM_EOF'
# ============================================
# Custom blocking entries - Android Guardian
# ============================================
# Custom blocking entries
# YouTube
0.0.0.0 youtube.com
0.0.0.0 www.youtube.com
@ -69,120 +334,331 @@ adb shell "su -c 'cat >> /data/adb/modules/systemless_hosts/system/etc/hosts <<
0.0.0.0 s.ytimg.com
0.0.0.0 i9.ytimg.com
0.0.0.0 googlevideo.com
0.0.0.0 r1---sn-4g5e6nls.googlevideo.com
0.0.0.0 r1---sn-4g5lne7s.googlevideo.com
# Steam Store
# Discord (selective blocking - media only, voice chat allowed)
# Discord (media only - voice chat allowed)
0.0.0.0 cdn.discordapp.com
0.0.0.0 media.discordapp.net
0.0.0.0 images-ext-1.discordapp.net
0.0.0.0 images-ext-2.discordapp.net
0.0.0.0 attachments-1.discordapp.net
0.0.0.0 attachments-2.discordapp.net
0.0.0.0 tenor.com
0.0.0.0 giphy.com
# Food Delivery Services
# Polish services
0.0.0.0 pyszne.pl
0.0.0.0 www.pyszne.pl
0.0.0.0 m.pyszne.pl
0.0.0.0 glovo.com
0.0.0.0 www.glovo.com
0.0.0.0 m.glovo.com
0.0.0.0 bolt.eu
0.0.0.0 food.bolt.eu
0.0.0.0 woltwojta.pl
0.0.0.0 www.woltwojta.pl
0.0.0.0 wolt.com
0.0.0.0 www.wolt.com
0.0.0.0 m.wolt.com
# International services
0.0.0.0 ubereats.com
0.0.0.0 www.ubereats.com
0.0.0.0 m.ubereats.com
0.0.0.0 uber.com
0.0.0.0 www.uber.com
0.0.0.0 m.uber.com
0.0.0.0 deliveroo.com
0.0.0.0 www.deliveroo.com
0.0.0.0 m.deliveroo.com
0.0.0.0 deliveroo.co.uk
0.0.0.0 www.deliveroo.co.uk
0.0.0.0 foodpanda.com
0.0.0.0 www.foodpanda.com
0.0.0.0 m.foodpanda.com
0.0.0.0 grubhub.com
0.0.0.0 www.grubhub.com
0.0.0.0 m.grubhub.com
0.0.0.0 doordash.com
0.0.0.0 www.doordash.com
0.0.0.0 m.doordash.com
0.0.0.0 justeat.com
0.0.0.0 www.justeat.com
0.0.0.0 m.justeat.com
0.0.0.0 justeat.co.uk
0.0.0.0 www.justeat.co.uk
0.0.0.0 postmates.com
0.0.0.0 www.postmates.com
0.0.0.0 seamless.com
0.0.0.0 www.seamless.com
0.0.0.0 menulog.com.au
0.0.0.0 www.menulog.com.au
0.0.0.0 delivery.com
0.0.0.0 www.delivery.com
# Fast food chain apps and websites
# Fast Food
0.0.0.0 mcdonalds.com
0.0.0.0 www.mcdonalds.com
0.0.0.0 m.mcdonalds.com
0.0.0.0 mcdonalds.pl
0.0.0.0 www.mcdonalds.pl
0.0.0.0 kfc.com
0.0.0.0 www.kfc.com
0.0.0.0 m.kfc.com
0.0.0.0 kfc.pl
0.0.0.0 www.kfc.pl
0.0.0.0 burgerking.com
0.0.0.0 www.burgerking.com
0.0.0.0 m.burgerking.com
0.0.0.0 burgerking.pl
0.0.0.0 www.burgerking.pl
0.0.0.0 pizzahut.com
0.0.0.0 www.pizzahut.com
0.0.0.0 m.pizzahut.com
0.0.0.0 pizzahut.pl
0.0.0.0 www.pizzahut.pl
0.0.0.0 dominos.com
0.0.0.0 www.dominos.com
0.0.0.0 m.dominos.com
0.0.0.0 dominos.pl
0.0.0.0 www.dominos.pl
0.0.0.0 subway.com
0.0.0.0 www.subway.com
0.0.0.0 m.subway.com
0.0.0.0 subway.pl
0.0.0.0 www.subway.pl
CUSTOM_EOF
'" || {
echo "[$(date +'%Y-%m-%d %H:%M:%S%z')] ✗ Failed to add custom entries"
exit 1
local total_entries
total_entries=$(grep -c "^0\.0\.0\.0 " "$hosts_file" || echo 0)
echo "[BUILD] Hosts file contains $total_entries blocked domains" >&2
# Create zip
(cd "$tmp_dir" && zip -r "$module_zip" . -x "*.DS_Store") >/dev/null
echo "$module_zip"
}
echo "[$(date +'%Y-%m-%d %H:%M:%S%z')] ✓ Custom entries added successfully"
# Install/update the guardian module
cmd_install() {
ensure_device_ready
# Count and display blocked domains
domain_count=$(adb shell "su -c 'cat /system/etc/hosts | grep -c \"^0.0.0.0\"'" 2>/dev/null | tr -d '\r')
if [[ -n $domain_count ]]; then
echo "[$(date +'%Y-%m-%d %H:%M:%S%z')] ✓ Total blocked domains: $domain_count"
local module_zip
module_zip=$(build_module)
log "Pushing module to device..."
adb push "$module_zip" /sdcard/android_guardian.zip || die "Failed to push module"
log "Installing module..."
adb shell "su -c 'mkdir -p $MODULE_DEST'" || die "Failed to create module directory"
adb shell "su -c 'cd $MODULE_DEST && unzip -o /sdcard/android_guardian.zip'" || die "Failed to extract module"
adb shell "su -c 'chmod 755 $MODULE_DEST/*.sh'"
adb shell "su -c 'rm /sdcard/android_guardian.zip'"
# Set up guardian data directory
log "Setting up guardian data..."
adb shell "su -c 'mkdir -p $GUARDIAN_DATA_DIR'"
adb shell "su -c 'echo ENABLED > $GUARDIAN_DATA_DIR/control'"
# Copy blocked apps list
adb push "$GUARDIAN_MODULE_DIR/blocked_apps.txt" /sdcard/blocked_apps.txt || die "Failed to push blocked apps list"
adb shell "su -c 'cp /sdcard/blocked_apps.txt $GUARDIAN_DATA_DIR/blocked_apps.txt'"
adb shell "su -c 'rm /sdcard/blocked_apps.txt'"
# Create hosts backup for tamper protection
adb shell "su -c 'cp $MODULE_DEST/system/etc/hosts $GUARDIAN_DATA_DIR/hosts.backup'"
# Immediately uninstall any currently installed blocked apps
log "Checking for blocked apps to remove..."
uninstall_blocked_apps
echo ""
echo "=========================================="
echo " ✓ Android Guardian installed!"
echo "=========================================="
echo ""
echo "Features enabled:"
echo " • Hosts-based ad/tracker blocking"
echo " • App installation blocking"
echo " • Tamper protection"
echo ""
echo "⚠️ This can ONLY be controlled via ADB:"
echo " Disable: $0 disable"
echo " Enable: $0 enable"
echo " Status: $0 status"
echo ""
echo "Reboot your device to activate the module."
echo ""
}
# Uninstall currently installed blocked apps
uninstall_blocked_apps() {
local blocked_apps
blocked_apps=$(grep -v '^#' "$GUARDIAN_MODULE_DIR/blocked_apps.txt" | grep -v '^$' || true)
for package in $blocked_apps; do
if adb shell "pm list packages" 2>/dev/null | grep -q "package:$package"; then
log "Uninstalling blocked app: $package"
adb shell "pm uninstall $package" 2>/dev/null || true
fi
done
}
# Show status
cmd_status() {
ensure_device_ready
echo ""
echo "=== Android Guardian Status ==="
echo ""
# Check if module is installed
if adb shell "su -c 'test -d $MODULE_DEST'" 2>/dev/null; then
echo "Module: INSTALLED"
else
echo "Module: NOT INSTALLED"
return
fi
echo "[$(date +'%Y-%m-%d %H:%M:%S%z')] ✓ Changes will take effect immediately for new connections"
echo "[$(date +'%Y-%m-%d %H:%M:%S%z')] (Optional: Toggle airplane mode or reboot to force all apps to reconnect)"
log "✓ Total blocked domains: $TOTAL_ENTRIES"
log ""
log "Changes will take effect immediately for new connections."
log "To apply to all apps, reboot the device or toggle airplane mode."
# Check control status
local status
status=$(adb shell "su -c 'cat $GUARDIAN_DATA_DIR/control 2>/dev/null || echo UNKNOWN'" | tr -d '\r')
echo "Status: $status"
# Check hosts file
local hosts_entries
hosts_entries=$(adb shell "su -c 'grep -c \"^0.0.0.0\" /system/etc/hosts 2>/dev/null || echo 0'" | tr -d '\r')
echo "Blocked domains: $hosts_entries"
# Check blocked apps count
local blocked_count
blocked_count=$(adb shell "su -c 'grep -v \"^#\" $GUARDIAN_DATA_DIR/blocked_apps.txt 2>/dev/null | grep -v \"^$\" | wc -l || echo 0'" | tr -d '\r')
echo "Blocked app rules: $blocked_count packages"
echo ""
}
# Disable guardian
cmd_disable() {
ensure_device_ready
log "Disabling Android Guardian..."
adb shell "su -c 'echo DISABLED > $GUARDIAN_DATA_DIR/control'" || die "Failed to disable guardian"
echo ""
echo "✓ Guardian DISABLED"
echo " Hosts blocking still active until reboot"
echo " App blocking service paused"
echo ""
echo "To re-enable: $0 enable"
echo ""
}
# Enable guardian
cmd_enable() {
ensure_device_ready
log "Enabling Android Guardian..."
adb shell "su -c 'echo ENABLED > $GUARDIAN_DATA_DIR/control'" || die "Failed to enable guardian"
echo ""
echo "✓ Guardian ENABLED"
echo ""
}
# Uninstall module
cmd_uninstall() {
ensure_device_ready
# Check if disabled first
local status
status=$(adb shell "su -c 'cat $GUARDIAN_DATA_DIR/control 2>/dev/null || echo ENABLED'" | tr -d '\r')
if [[ "$status" != "DISABLED" ]]; then
echo ""
echo "⚠️ Guardian must be disabled before uninstalling!"
echo " Run: $0 disable"
echo " Then: $0 uninstall"
echo ""
exit 1
fi
log "Removing Android Guardian..."
adb shell "su -c 'rm -rf $MODULE_DEST'"
adb shell "su -c 'rm -rf $GUARDIAN_DATA_DIR'"
echo ""
echo "✓ Guardian uninstalled"
echo " Reboot to remove hosts blocking"
echo ""
}
# Show logs
cmd_logs() {
ensure_device_ready
echo "=== Guardian Logs ==="
adb shell "su -c 'cat $GUARDIAN_DATA_DIR/guardian.log 2>/dev/null || echo \"No logs yet\"'"
}
# Block an app
cmd_block_app() {
local package="${1:-}"
if [[ -z "$package" ]]; then
echo "Usage: $0 block-app <package.name>"
echo "Example: $0 block-app com.ubercab.eats"
exit 1
fi
ensure_device_ready
log "Adding $package to block list..."
adb shell "su -c 'echo \"$package\" >> $GUARDIAN_DATA_DIR/blocked_apps.txt'"
# Also add to local file
echo "$package" >>"$GUARDIAN_MODULE_DIR/blocked_apps.txt"
# Try to uninstall if currently installed
if adb shell "pm list packages" 2>/dev/null | grep -q "package:$package"; then
log "Uninstalling $package..."
adb shell "pm uninstall $package" 2>/dev/null || true
fi
echo "$package added to block list"
}
# Unblock an app
cmd_unblock_app() {
local package="${1:-}"
if [[ -z "$package" ]]; then
echo "Usage: $0 unblock-app <package.name>"
exit 1
fi
ensure_device_ready
log "Removing $package from block list..."
adb shell "su -c 'grep -v \"^$package\$\" $GUARDIAN_DATA_DIR/blocked_apps.txt > $GUARDIAN_DATA_DIR/blocked_apps.tmp && mv $GUARDIAN_DATA_DIR/blocked_apps.tmp $GUARDIAN_DATA_DIR/blocked_apps.txt'"
# Also remove from local file
grep -v "^$package$" "$GUARDIAN_MODULE_DIR/blocked_apps.txt" >"$GUARDIAN_MODULE_DIR/blocked_apps.tmp" && mv "$GUARDIAN_MODULE_DIR/blocked_apps.tmp" "$GUARDIAN_MODULE_DIR/blocked_apps.txt"
echo "$package removed from block list"
}
# List blocked apps
cmd_list_blocked() {
ensure_device_ready
echo "=== Blocked Apps ==="
adb shell "su -c 'cat $GUARDIAN_DATA_DIR/blocked_apps.txt 2>/dev/null'" | grep -v "^#" | grep -v "^$" || echo "No blocked apps"
}
# Main
# Initialize Android script (handles sudo, sets WORK_DIR)
init_android_script "$@"
COMMAND="${1:-install}"
shift || true
case "$COMMAND" in
install)
cmd_install
;;
status)
cmd_status
;;
disable)
cmd_disable
;;
enable)
cmd_enable
;;
uninstall)
cmd_uninstall
;;
logs)
cmd_logs
;;
block-app)
cmd_block_app "$@"
;;
unblock-app)
cmd_unblock_app "$@"
;;
list-blocked)
cmd_list_blocked
;;
pair)
cmd_pair
;;
connect)
cmd_connect
;;
disconnect)
cmd_disconnect
;;
-h | --help | help)
show_usage
;;
*)
echo "Unknown command: $COMMAND"
show_usage
exit 1
;;
esac