# Importa a biblioteca nativa 'zlib' usada para descompressão de dados binários. import base64 import zlib # Define uma classe utilitária chamada 'String', contendo apenas métodos estáticos. # Essa abordagem permite o uso direto sem necessidade de instanciar a classe. class String: @staticmethod def decompress(vf_string): """ Descomprime e decodifica texto de origem WPTools/Firebird. Finalidade: Converter o conteúdo de campos BLOB ou strings compactadas (como no Delphi) em texto legível, detectando automaticamente se o conteúdo está: - Compactado com zlib - Codificado em ISO-8859-1 (padrão ANSI) - Representado como bytes puros """ # Verifica se o valor recebido é nulo, vazio ou None. # Se for, retorna string vazia para evitar erros de processamento. if not vf_string: return "" # Caso seja um objeto tipo stream (ex: campo BLOB do Firebird) # Campos BLOB geralmente possuem o método `.read()` para leitura de bytes. if hasattr(vf_string, "read"): vf_string = vf_string.read() # Lê o conteúdo completo do stream # Garante que o valor trabalhado é uma sequência de bytes (não string) # Se o dado já for texto (str), converte para bytes em codificação Latin-1, # que é compatível com ISO-8859-1 usado por sistemas Delphi/Firebird. if isinstance(vf_string, str): vf_bytes = vf_string.encode("latin1", errors="ignore") else: vf_bytes = vf_string # Já está em bytes, então apenas reaproveita # Detecta se o conteúdo foi compactado com zlib. # A assinatura padrão do formato zlib começa com bytes: 0x78 0x9C ou 0x78 0xDA. is_zlib = ( len(vf_bytes) > 2 and vf_bytes[0] == 0x78 and vf_bytes[1] in (0x9C, 0xDA) ) # Se a detecção confirmar que o conteúdo é zlib, tenta descompactar. if is_zlib: try: # Descompacta os bytes e decodifica o texto usando ISO-8859-1 (ANSI), # que preserva corretamente acentuação e caracteres especiais. text = zlib.decompress(vf_bytes).decode("iso-8859-1", errors="ignore") return text except Exception: # Caso falhe (por dados corrompidos ou não comprimidos de fato), # o fluxo continua normalmente sem interromper a execução. pass # Se não for zlib, tenta tratar o conteúdo como texto puro (não compactado) try: # Decodifica os bytes diretamente de ISO-8859-1 (padrão usado pelo Delphi) return vf_bytes.decode("iso-8859-1", errors="ignore") except Exception: # Como fallback, converte para string bruta para evitar falhas. return str(vf_string) # >>> NOVO MÉTODO <<< @staticmethod def compress(text, *, encoding: str = "iso-8859-1", as_base64: bool = True): """ Comprime texto/dados com zlib. Parâmetros: text: str | bytes | stream (com .read()) encoding: encoding usado quando 'text' for str (padrão: ISO-8859-1) as_base64: se True, retorna string Base64 do conteúdo comprimido; caso False, retorna bytes comprimidos. Retorno: - bytes (zlib) quando as_base64=False - str (Base64) quando as_base64=True Observações: - Use o mesmo 'encoding' ao descomprimir para simetria. - Ideal para armazenar em BLOB ou trafegar seguro (Base64). """ if text is None or text == "": return "" if as_base64 else b"" # Se for stream (ex.: BLOB do Firebird) if hasattr(text, "read"): raw = text.read() else: raw = text # Garante bytes if isinstance(raw, str): raw_bytes = raw.encode(encoding, errors="ignore") else: raw_bytes = bytes(raw) # Comprime com zlib comp = zlib.compress(raw_bytes) # Opcional: codifica em Base64 para transporte/JSON if as_base64: return base64.b64encode(comp).decode("ascii") return comp