Last active
December 13, 2024 17:49
-
-
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.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/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://gitflic.ru/project/magnolia1234/bpc_uploads/blob/raw?file=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://gitflic.ru/project/magnolia1234/bpc_uploads/blob/raw?file=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