diff --git a/sab2sax.py b/sab2sax.py deleted file mode 100644 index 5c677ce..0000000 --- a/sab2sax.py +++ /dev/null @@ -1,155 +0,0 @@ -#!/usr/bin/env python3 -""" -Convert Sedona .sab binary file to .sax XML format -Final working version based on hex dump analysis -""" - -import sys -import os -import struct -from pathlib import Path - -def read_null_string(data, offset): - """Read a null-terminated string""" - start = offset - while offset < len(data) and data[offset] != 0: - offset += 1 - if offset >= len(data): - return None, offset - string = data[start:offset].decode('ascii') - offset += 1 # Skip null - return string, offset - -def sab_to_sax(input_file): - """Convert .sab file to .sax XML format""" - - # Read binary file - with open(input_file, 'rb') as f: - sab_data = f.read() - - offset = 0 - - # Check magic number - magic = sab_data[0:4].decode('ascii') - if magic != "sapp": - print(f"Error: Not a valid Sedona binary file") - return - - offset += 4 - print(f"āœ“ Valid Sedona app file detected") - - # Version (2 bytes) - version = struct.unpack_from('>H', sab_data, offset)[0] - offset += 2 - - # Kit count - kit_count = struct.unpack_from('>H', sab_data, offset)[0] - offset += 2 - - # Read kit names and checksums - kits = [] - for i in range(kit_count): - kit_name, offset = read_null_string(sab_data, offset) - checksum = struct.unpack_from('>I', sab_data, offset)[0] - offset += 4 - kits.append((kit_name, checksum)) - print(f" Found kit: {kit_name}") - - # Start XML output - sax_xml = '\n' - sax_xml += f'\n\n' - sax_xml += ' \n' - - # Group types by kit (based on prefixes in the names) - kit_types = {kit[0]: [] for kit in kits} - - # Read all type names and their data - type_id = 1 - while offset < len(sab_data): - try: - # Read type name - type_name, new_offset = read_null_string(sab_data, offset) - if type_name is None: - break - - # Determine which kit this type belongs to - assigned_kit = None - for kit_name in kit_types.keys(): - if type_name.startswith(kit_name) or kit_name in type_name: - assigned_kit = kit_name - break - - if not assigned_kit: - assigned_kit = kits[0][0] # Default to first kit - - # Read the 4 bytes after the name (type data) - if new_offset + 4 <= len(sab_data): - type_data = struct.unpack_from('>I', sab_data, new_offset)[0] - new_offset += 4 - - # Store type info - kit_types[assigned_kit].append({ - 'id': type_id, - 'name': type_name, - 'data': type_data - }) - type_id += 1 - - offset = new_offset - - except Exception as e: - print(f" Warning: Stopped parsing at offset {offset}: {e}") - break - - # Write XML for each kit - for kit_name, checksum in kits: - types = kit_types.get(kit_name, []) - sax_xml += f' \n' - - for t in types: - sax_xml += f' \n' - - sax_xml += ' \n' - - sax_xml += ' \n\n' - - # Add placeholder for app and links - sax_xml += ' \n' - sax_xml += ' \n' - sax_xml += ' \n\n' - - sax_xml += ' \n' - sax_xml += ' \n' - sax_xml += ' \n' - - sax_xml += '' - - # Write output file - output_file = str(Path(input_file).with_suffix('.sax')) - with open(output_file, 'w', encoding='utf-8') as f: - f.write(sax_xml) - - print(f"\nāœ“ Successfully converted: {input_file} -> {output_file}") - print(f" Found {type_id-1} total types across {len(kits)} kits") - -def main(): - if len(sys.argv) != 2: - print("Usage: python sab_to_sax.py ") - sys.exit(1) - - input_file = sys.argv[1] - - if not os.path.exists(input_file): - print(f"Error: File not found: {input_file}") - sys.exit(1) - - try: - sab_to_sax(input_file) - except Exception as e: - print(f"Error converting file: {e}") - import traceback - traceback.print_exc() - sys.exit(1) - -if __name__ == "__main__": - main() \ No newline at end of file