From 031e274b8178896b8f847aad0701b5e2700c527f Mon Sep 17 00:00:00 2001
From: jooapa <jooa.akonpelto@gmail.com>
Date: Sat, 3 Feb 2024 23:14:10 +0200
Subject: [PATCH] Refactor decrypting logic and improve file handling, can
 decrypt whole folders

---
 README.md  |   6 ++-
 birdout.py | 141 +++++++++++++++++++++++++++++++++--------------------
 2 files changed, 93 insertions(+), 54 deletions(-)

diff --git a/README.md b/README.md
index 3e2974b..0bb45fe 100644
--- a/README.md
+++ b/README.md
@@ -4,7 +4,7 @@
 
 If you don't know how to install Angry Birds PC ports, [here](https://archive.org/details/angry-birds-pc) is a link to the Internet Archive page for the PC ports of Angry Birds.
 
-### Automatic Usage (only for decrypting)
+### Automatic decrypting
 
 Firstly install [Python 3](https://www.python.org/downloads/).
 
@@ -15,6 +15,10 @@ or you can run it in the terminal with:
 
     python birdout.py <file.lua> <file.lua> ...
 
+passing only a folder will decrypt all .lua files in the directory.
+
+    python birdout.py <directory>
+
 Understandable, if you don't trust the .exe or the .jar file: openssl.exe. here is a virustotal scan: [virustotal](https://www.virustotal.com/gui/file/be0f086b9303fd52b6f5ec094c753c2b68f02559eb462f23929e72a6996eb1f8/detection/f-be0f086b9303fd52b6f5ec094c753c2b68f02559eb462f23929e72a6996eb1f8-1703249224)
 and here scan for the unluac.jar: [virustotal](https://www.virustotal.com/gui/file/50f23c0b1cb85cc2bd07055ce782a918fdcb5d36d18d268b9606298d801bbb6e/detection/f-50f23c0b1cb85cc2bd07055ce782a918fdcb5d36d18d268b9606298d801bbb6e-1689512688)
 
diff --git a/birdout.py b/birdout.py
index 8494ded..94895a0 100644
--- a/birdout.py
+++ b/birdout.py
@@ -1,15 +1,49 @@
 import os, sys, subprocess
 import py7zr
 
-if len(sys.argv) == 0:
+files = sys.argv[1:]
+# counting the number of directories
+
+org_path = os.path.dirname(os.path.realpath(__file__))
+# get directory of first file
+path_to_go = os.path.dirname(files[0])
+
+if len(files) == 0:
     print("Usage: birdout.py <file.lua> <file.lua> ...")
+    print("You can also pass a directory as an argument to decrypt all .lua files in it.")
     sys.exit(1)
+    
 
-for file in sys.argv[1:]:
+for file in files:
+    # if directory
+    if os.path.isdir(file):
+        # loop through all files in directory and if extension is .lua, add to list
+        for root, dirs, files in os.walk(file):
+            for file in files:
+                if file.endswith(".lua"):
+                    file = os.path.join(root, file)
+                    print("File: " + file)
+        
     if not os.path.isfile(file):
         print("File not found: " + file)
-        sys.exit(1) 
+        # remove file from list
+        files.remove(file)
+
+if len(files) == 0:
+    print("No valid files found!")
+    sys.exit(1)
+
+# go to directory of first file
+os.chdir(path_to_go)
+# remove the path from files
+files = [os.path.basename(file) for file in files]
+
+print("\nAngry Birds Lua Decryptor, works on for decrypting Angry Birds Lua files.")
+print("For Encrypting Luad files back,  Chech README.md")
+print("nöf nöf!")
 
+print("\nDecrypting files: " + str(files))
+      
 inp = input('''
 CHOOSE Angry Birds Game:
 1. Angry Birds
@@ -21,64 +55,65 @@
             ''')
 
 if inp == '1':   # Angry Birds
-  hex = "55534361505170413454534E56784D49317639534B39554330795A75416E6232"
+    hex = "55534361505170413454534E56784D49317639534B39554330795A75416E6232"
 elif inp == '2': # Angry Birds Rio
-  hex = "55534361505170413454534E56784D49317639534B39554330795A75416E6232"
+    hex = "55534361505170413454534E56784D49317639534B39554330795A75416E6232"
 elif inp == '3': # Angry Birds Seasons
-  hex = "7A65506865737435666151755832533241707265403472654368417445765574"
+    hex = "7A65506865737435666151755832533241707265403472654368417445765574"
 elif inp == '4': # Angry Birds Space
-  hex = "526D67645A304A656E4C466757776B5976434C326C5361684662456846656334"
+    hex = "526D67645A304A656E4C466757776B5976434C326C5361684662456846656334"
 elif inp == '5': # Angry Birds Star Wars
-  hex = "416E3874336D6E38553673706951307A4848723361316C6F44725261336D7445"
+    hex = "416E3874336D6E38553673706951307A4848723361316C6F44725261336D7445"
 elif inp == '6': # Angry Birds Star Wars II
-  hex = "4230706D3354416C7A6B4E3967687A6F65324E697A456C6C50644E3068516E69"
-
+    hex = "4230706D3354416C7A6B4E3967687A6F65324E697A456C6C50644E3068516E69"
+else:
+    print("Invalid input! nöf nöf!")
+    sys.exit(1)
 
 def extract_7z(archive_path, extract_path):
-    with py7zr.SevenZipFile(archive_path, mode='r') as archive:
-        archive.extractall(extract_path)
-
-def encrypt_file(hex, file, output_file):
-    if os.path.isfile(file):
-      # if windows
-      if os.name == 'nt':
-        print("Encrypting " + file + "...")
-        subprocess.call(["bin/openssl.exe", "enc", "-aes-256-cbc", "-d", "-K", hex, "-iv", "0", "-in", file, "-out", output_file])
-        extract_7z(output_file, extract_path)
-        os.remove(output_file)
-        os.remove(file)
-        # run java -jar bin/unluac.jar out/<file> > out/<file>.lua
-        subprocess.call(["java", "-jar", "bin/unluac.jar", "out/" + file], stdout=open("out/" + file + ".decypt", "w"))
-        # move decrypted file to root
-        os.rename("out/" + file + ".decypt", file)
-        # remove out folder and its contents
-        os.remove("out/" + file)
-        os.rmdir("out")
-
-        print("Done!")
-      # if linux use wine
-      elif os.name == 'posix':
-        print("Encrypting " + file + "...")
-        subprocess.call(["wine", "bin/openssl.exe", "enc", "-aes-256-cbc", "-d", "-K", hex, "-iv", "0", "-in", file, "-out", output_file])
-        extract_7z(output_file, extract_path)
-        os.remove(output_file)
-        os.remove(file)
-        # run java -jar bin/unluac.jar out/<file> > out/<file>.lua
-        subprocess.call(["java", "-jar", "bin/unluac.jar", "out/" + file], stdout=open("out/" + file + ".decypt", "w"))
-        # move decrypted file to root
-        os.rename("out/" + file + ".decypt", file)
-        # remove out folder and its contents
-        os.remove("out/" + file)
-        os.rmdir("out")
-
-        print("Done!")
-    else:
-        print("File not found!")
-
-output_file = file + ".7z"
+    print("Extracting " + archive_path + "...")
+    try:
+        with py7zr.SevenZipFile(archive_path, mode='r') as archive:
+            archive.extractall(extract_path)
+    except py7zr.exceptions.Bad7zFile:
+        print("Error: Not a 7z archive! File might be corrupted somehow or it already has been decrypted.")
+        os.remove(archive_path)
+        sys.exit(1)
+
+def decrypt_file(hex, file):
+    print("Decrypting " + file + "...")
+    output_file = file + ".7z"
+    
+    combined_path = os.path.join(org_path, "bin/openssl")
+    if os.name == 'nt':
+        decryption_result = subprocess.run([combined_path, "enc", "-aes-256-cbc", "-d", "-K", hex, "-iv", "0", "-in", file, "-out", output_file], capture_output=True)
+    elif os.name == 'posix':
+        decryption_result = subprocess.run(["wine", combined_path, "enc", "-aes-256-cbc", "-d", "-K", hex, "-iv", "0", "-in", file, "-out", output_file], capture_output=True)
+
+    if decryption_result.returncode != 0:
+        print("You might have entered the wrong game file or the file is corrupted. Decrypting failed! nöf nöf!")
+        os.remove(file + ".7z")
+        sys.exit(1)
+    
+    extract_7z(output_file, extract_path)
+    os.remove(output_file)
+    os.remove(file)
+    # run java -jar bin/unluac.jar out/<file> > out/<file>.lua
+    combined_jar_path = os.path.join(org_path, "bin/unluac.jar")
+    # subprocess.call(["java", "-jar", "bin/unluac.jar", "out/" + file], stdout=open("out/" + file + ".decrypt", "w"))
+    subprocess.call(["java", "-jar", combined_jar_path, "out/" + file], stdout=open("out/" + file + ".decrypt", "w"))
+    # move decrypted file to root
+    os.rename("out/" + file + ".decrypt", file)
+    # remove out folder and its contents
+    os.remove("out/" + file)
+    os.rmdir("out")
+
+    print("Done!", file + " decrypted!")
+
 extract_path = "out"
 
 # for loop encrypts all files passed as arguments
-for file in sys.argv[1:]:
-    encrypt_file(hex, file, output_file)
+for file in files:
+    decrypt_file(hex, file)
 
+print("nöf nöf!")