commit 5e78e994606b68bb9ba2429d5f2341984f3b371e Author: godax84 Date: Mon Feb 3 03:24:46 2025 -0800 Carregar ficheiros para "/" diff --git a/ICON.ico b/ICON.ico new file mode 100644 index 0000000..0f4fd42 Binary files /dev/null and b/ICON.ico differ diff --git a/main.py b/main.py new file mode 100644 index 0000000..f238b07 --- /dev/null +++ b/main.py @@ -0,0 +1,163 @@ +import tkinter as tk +from tkinter import filedialog, ttk, messagebox +import re +from typing import Tuple, List +from collections import Counter + +class PSADecoder: + def __init__(self): + # Tabela de decodificação exata do PDF (Table 1) + self.decode_table = { + 0xCF: '0', 0xCE: '1', 0xCD: '2', 0xCC: '3', 0xCB: '4', + 0xCA: '5', 0xC9: '6', 0xC8: '7', 0xC7: '8', 0xC6: '9', + 0xBE: 'A', 0xBD: 'B', 0xBC: 'C', 0xBB: 'D', 0xBA: 'E', + 0xB9: 'F', 0xB8: 'G', 0xB7: 'H', 0xB6: 'I', 0xB5: 'J', + 0xB4: 'K', 0xB3: 'L', 0xB2: 'M', 0xB1: 'N', 0xB0: 'O', + 0xAF: 'P', 0xAE: 'Q', 0xAD: 'R', 0xAC: 'S', 0xAB: 'T', + 0xAA: 'U', 0xA9: 'V', 0xA8: 'W', 0xA7: 'X', 0xA6: 'Y', + 0xA5: 'Z' + } + + def decode_bytes(self, data: bytes) -> str: + decoded = '' + for byte in data: + if byte in self.decode_table: + decoded += self.decode_table[byte] + else: + decoded += ' ' # Substitui caracteres não encontrados na tabela por espaço + return decoded + +class VINPINFinder(tk.Tk): + def __init__(self): + super().__init__() + self.decoder = PSADecoder() + + self.title("Decodificador BSI PSA - VIN/PIN Finder") + self.geometry("800x600") + + # Criar o frame principal + main_frame = ttk.Frame(self, padding="10") + main_frame.grid(row=0, column=0, sticky=(tk.W, tk.E, tk.N, tk.S)) + + # Botão para selecionar arquivo + self.select_button = ttk.Button( + main_frame, + text="Selecionar Arquivo BSI", + command=self.select_file + ) + self.select_button.grid(row=0, column=0, pady=10, sticky=tk.W) + + self.select_buttonb = ttk.Button(main_frame, text="About", command=self.show_about) + self.select_buttonb.grid(row=0, column=1, pady=10, sticky=tk.W) + + # Label para mostrar o arquivo selecionado + self.file_label = ttk.Label(main_frame, text="Nenhum arquivo selecionado") + self.file_label.grid(row=1, column=0, pady=5, sticky=tk.W) + + # Frame para resultados + results_frame = ttk.LabelFrame(main_frame, text="Resultados da Decodificação", padding="5") + results_frame.grid(row=2, column=0, pady=10, sticky=(tk.W, tk.E, tk.N, tk.S)) + + # Texto para mostrar resultados + self.results_text = tk.Text(results_frame, height=20, width=80) + self.results_text.grid(row=0, column=0, pady=5) + + # Scrollbar para resultados + scrollbar = ttk.Scrollbar(results_frame, orient=tk.VERTICAL, command=self.results_text.yview) + scrollbar.grid(row=0, column=1, sticky=(tk.N, tk.S)) + self.results_text.configure(yscrollcommand=scrollbar.set) + + def validate_vin_occurrences(self, vins: List[str]) -> List[str]: + """Valida VINs que aparecem entre 2 e 3 vezes""" + counter = Counter(vins) + valid_vins = [vin for vin, count in counter.items() if 2 <= count <= 3] + return valid_vins + + def find_isolated_pin(self, decoded_content: str) -> str: + """ + Procura por um PIN isolado (4 caracteres alfanuméricos com não-alfanuméricos ao redor) + Usa lookbehind e lookahead para garantir que o PIN está isolado + """ + # Padrão modificado: + # (?