Skip to content

Instantly share code, notes, and snippets.

@cspence001
Last active September 5, 2024 19:08
Show Gist options
  • Save cspence001/33302cf180212a22423e4abcd2aa7868 to your computer and use it in GitHub Desktop.
Save cspence001/33302cf180212a22423e4abcd2aa7868 to your computer and use it in GitHub Desktop.
Updates the BPC Chrome extension (installed via "Load Unpacked" in Developer Mode) after verifying the SHA-256 hash of the extension’s ZIP file. On match, the script extracts and updates the extension.
#!/usr/bin/env python3
# Verifies the SHA-256 hash of a downloaded file from (https://gitflic.ru/project/magnolia1234/bpc_uploads) against the hash in [release-hashes.txt](https://github.com/bpc-clone/bypass-paywalls-chrome-clean/blob/master/release-hashes.txt).
# 1. Downloads the hash file from the [HASH_URL] and extracts the expected hash for the correspondent [FILENAME].
# 2. Downloads the zip-file [FILENAME] from [DOWNLOAD_URL] and calculates its SHA-256 hash.
# 3. Compares the calculated hash with the expected hash.
# 4. On match, prompts the user to move the file to a permanent location [DOWNLOAD_DIR].
# 5. Moves and extracts the file if confirmed; otherwise, deletes the temporary file.
# Note: Before running script, replace [DOWNLOAD_DIR] with permanent location on your computer that you use for your extension, excluding the extracted folder name [EXTRACT_DIR_NAME].
import requests
import hashlib
import re
import tempfile
import os
import shutil
import zipfile
import json
# Constants
HASH_URL = "https://raw.githubusercontent.com/bpc-clone/bypass-paywalls-chrome-clean/master/release-hashes.txt"
FILENAME = "bypass-paywalls-chrome-clean-master.zip"
DOWNLOAD_URL = f"https://gitflic.ru/project/magnolia1234/bpc_uploads/blob/raw?file={FILENAME}"
DOWNLOAD_DIR = os.path.expanduser("~/folder/macsetup/_packages/bpc-gitflic") # Replace with permanent location
EXTRACT_DIR_NAME = "bypass-paywalls-chrome-clean-master" # Extracted folder name within the zip file
EXTRACT_DIR_PATH = os.path.join(DOWNLOAD_DIR, EXTRACT_DIR_NAME)
COLOR_YELLOW = "\033[0;33m"
COLOR_RESET = "\033[0m"
def fetch_hash_file(url):
response = requests.get(url)
response.raise_for_status()
return response.text
def extract_hash(content, filename):
# Regex to find the hash block for the specified filename
pattern = re.compile(
rf'Filename\s+:\s+{re.escape(filename)}.*?SHA-256\s+:\s+(\S+)',
re.DOTALL
)
match = pattern.search(content)
if match:
return match.group(1)
raise ValueError(f"Hash for {filename} not found in release hashes.")
def download_file(url, local_path):
response = requests.get(url, stream=True)
response.raise_for_status()
with open(local_path, 'wb') as file:
for chunk in response.iter_content(chunk_size=8192):
file.write(chunk)
def compute_sha256(file_path):
sha256 = hashlib.sha256()
with open(file_path, 'rb') as file:
while chunk := file.read(8192):
sha256.update(chunk)
return sha256.hexdigest()
def extract_zip(zip_path, extract_to):
with zipfile.ZipFile(zip_path, 'r') as zip_ref:
# Extract to a temporary directory to handle extraction
temp_extract_dir = os.path.join(DOWNLOAD_DIR, 'temp_extract')
os.makedirs(temp_extract_dir, exist_ok=True)
zip_ref.extractall(temp_extract_dir)
# Move extracted folder to the final location
extracted_folder_path = os.path.join(temp_extract_dir, EXTRACT_DIR_NAME)
if os.path.isdir(extracted_folder_path):
replace_existing_folder(extract_to)
shutil.move(extracted_folder_path, extract_to)
else:
raise ValueError(f"Expected folder {EXTRACT_DIR_NAME} not found in ZIP file.")
shutil.rmtree(temp_extract_dir) # Clean up the temporary extraction directory
def replace_existing_folder(path):
if os.path.exists(path):
print(f"Removing existing folder: {path}")
shutil.rmtree(path)
def read_version_from_manifest(path):
manifest_path = os.path.join(path, 'manifest.json')
with open(manifest_path, 'r') as file:
manifest = json.load(file)
return manifest.get('version', 'unknown')
def main():
# Fetch the release hashes file
print("Fetching release hashes...")
hash_content = fetch_hash_file(HASH_URL)
# Extract the expected SHA-256 hash for the specific filename
print(f"Extracting SHA-256 hash for {FILENAME}...")
expected_hash = extract_hash(hash_content, FILENAME)
print(f"Extracted SHA-256 hash: {expected_hash}")
# Create temporary files
with tempfile.NamedTemporaryFile(delete=False) as temp_file:
download_file(DOWNLOAD_URL, temp_file.name)
temp_file_path = temp_file.name
print(f"File downloaded to: {temp_file_path}")
# Compute the SHA-256 hash of the downloaded file
print("Computing SHA256 hash...")
computed_hash = compute_sha256(temp_file_path)
# Compare hashes
if computed_hash == expected_hash:
print(f"Hash match: {computed_hash}")
# Read current version from existing manifest
old_version = 'unknown'
if os.path.exists(EXTRACT_DIR_PATH):
old_version = read_version_from_manifest(EXTRACT_DIR_PATH)
print(f"Current version: {old_version}")
# Extract the new version from the ZIP file
with zipfile.ZipFile(temp_file_path, 'r') as zip_ref:
with zip_ref.open(os.path.join(EXTRACT_DIR_NAME, 'manifest.json')) as manifest_file:
new_manifest = json.load(manifest_file)
new_version = new_manifest.get('version', 'unknown')
print(f"Latest version: {new_version}")
if old_version == new_version:
print("The extension is up to date.")
os.remove(temp_file_path)
else:
# Ask the user if they want to move the file to the permanent location
user_input = input("Do you want to move the file to the permanent location? (y/n): ").strip().lower()
if user_input == 'y':
permanent_location = os.path.join(DOWNLOAD_DIR, FILENAME)
os.makedirs(DOWNLOAD_DIR, exist_ok=True)
if os.path.exists(permanent_location):
print(f"File already exists at {permanent_location}. Replacing it.")
shutil.move(temp_file_path, permanent_location)
print(f"File moved to: {permanent_location}")
# Extract the ZIP file
print("Extracting ZIP file...")
extract_zip(permanent_location, EXTRACT_DIR_PATH)
print(f"Files extracted to: {EXTRACT_DIR_PATH}")
print(f"{COLOR_YELLOW}Updated {old_version} to {new_version}{COLOR_RESET}")
print(f"{COLOR_YELLOW}Restart your browser for changes to take effect.{COLOR_RESET}")
else:
print("File not moved.")
os.remove(temp_file_path)
else:
print(f"Hash mismatch: computed {computed_hash}, expected {expected_hash}")
os.remove(temp_file_path)
if __name__ == "__main__":
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment