#!/usr/bin/env python

"""
cloak.py - Simple file encryption/compression utility

Copyright (c) 2006-2024 sqlmap developers (https://sqlmap.org/)
See the file 'LICENSE' for copying permission
"""

from __future__ import print_function  # 兼容 Python 2 和 3 的 print 函数

import os
import struct
import sys
import zlib  # 用于数据压缩和解压缩

from optparse import OptionError
from optparse import OptionParser

# 在 Python 3 中定义 xrange 和 ord 的兼容
if sys.version_info >= (3, 0):
    xrange = range  # 使用 Python 3 的 range
    ord = lambda _: _  # 在 Python 3 中直接使用字符

KEY = b"E6wRbVhD0IBeCiGJ"  # 定义加密/解密的密钥

def xor(message, key):
    """执行 XOR 操作，返回加密或解密后的字节序列。"""
    # 对 message 的每个字节进行 XOR 运算，并返回字节串
    return b"".join(struct.pack('B', ord(message[i]) ^ ord(key[i % len(key)])) for i in range(len(message)))

def cloak(inputFile=None, data=None):
    """对输入文件或数据进行加密和压缩。"""
    if data is None:
        # 如果没有提供数据，则读取文件内容
        with open(inputFile, "rb") as f:
            data = f.read()  # 以二进制模式读取文件数据

    # 对数据进行压缩后再使用 XOR 加密
    return xor(zlib.compress(data), KEY)

def decloak(inputFile=None, data=None):
    """对输入文件或数据进行解密和解压缩。"""
    if data is None:
        # 如果没有提供数据，则读取文件内容
        with open(inputFile, "rb") as f:
            data = f.read()

    try:
        # 首先对数据进行 XOR 解密，然后解压缩
        data = zlib.decompress(xor(data, KEY))
    except Exception as ex:
        # 如果解压缩过程中发生异常，打印错误信息并退出
        print(ex)
        print('ERROR: the provided input file \'%s\' does not contain valid cloaked content' % inputFile)
        sys.exit(1)
    finally:
        f.close()  # 确保文件流被关闭

    return data  # 返回解密后的数据

def main():
    """主函数，负责解析命令行参数并执行加密或解密操作。"""
    usage = '%s [-d] -i <input file> [-o <output file>]' % sys.argv[0]  # 使用说明
    parser = OptionParser(usage=usage, version='0.2')  # 创建 OptionParser 对象

    try:
        # 添加命令行选项
        parser.add_option('-d', dest='decrypt', action="store_true", help='Decrypt')  # 解密选项
        parser.add_option('-i', dest='inputFile', help='Input file')  # 输入文件选项
        parser.add_option('-o', dest='outputFile', help='Output file')  # 输出文件选项

        (args, _) = parser.parse_args()  # 解析命令行参数

        if not args.inputFile:
            parser.error('Missing the input file, -h for help')  # 如果未提供输入文件，则报错

    except (OptionError, TypeError) as ex:
        parser.error(ex)  # 捕获解析错误

    # 检查输入文件是否存在
    if not os.path.isfile(args.inputFile):
        print('ERROR: the provided input file \'%s\' is non existent' % args.inputFile)
        sys.exit(1)

    # 根据是否需要解密选择处理函数
    if not args.decrypt:
        data = cloak(args.inputFile)  # 加密文件内容
    else:
        data = decloak(args.inputFile)  # 解密文件内容

    # 如果未指定输出文件名，则根据是否解密自动生成
    if not args.outputFile:
        if not args.decrypt:
            args.outputFile = args.inputFile + '_'  # 添加后缀表示加密
        else:
            args.outputFile = args.inputFile[:-1]  # 移除后缀表示解密

    # 写入结果到输出文件
    f = open(args.outputFile, 'wb')
    f.write(data)  # 写入数据
    f.close()  # 关闭文件

if __name__ == '__main__':
    main()  # 程序入口