/*
文件名:MD5Class.nut
路径:Dps_A/BaseClass/MD5Class/MD5Class.nut
创建日期:2024-09-20	00:06
文件用途:MD5类
*/
class MD5 {
    MD5_Init_ptr = Module.getExportByName(null, "MD5_Init");
    MD5_Update_ptr = Module.getExportByName(null, "MD5_Update");
    MD5_Final_ptr = Module.getExportByName(null, "MD5_Final");

    function MD5_Init(Ctx) {
        Sq_CallFunc(MD5_Init_ptr, "void", ["pointer"], Ctx);
    }

    function MD5_Update(Ctx, Buffer, Size) {
        Sq_CallFunc(MD5_Update_ptr, "void", ["pointer", "pointer", "int"], Ctx, Buffer, Size);
    }

    function MD5_Final(Ctx, Result) {
        Sq_CallFunc(MD5_Final_ptr, "void", ["pointer", "pointer"], Ctx, Result);
    }

    // 16进制编码函数
    // 参数: input - 可以是字符串或字节数组或Memory对象
    // 返回: 32位16进制小写字符串（默认格式）
    function hex_encode(input) {
        local byteArray = [];

        // 如果输入是字符串，转换为字节数组
         if (typeof input == "string") {
            for (local i = 0; i < input.len(); i++) {
                byteArray.append(input[i].tointeger() & 0xFF);
            }
        }
        // 如果输入是数组，直接使用
        else {
            byteArray = input;
        }

        local encoded = "";

        for (local i = 0; i < byteArray.len(); i++) {
            local byte = byteArray[i] & 0xFF;
            encoded += format("%02x", byte);
        }

        return encoded;
    }

    // Base64 编码函数
    // 参数: input - 可以是字符串或字节数组
    // 返回: base64 编码后的字符串
    function base64_encode(input) {
        local base64_chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";

        // 如果输入是字符串，转换为字节数组
        local byteArray = [];
        if (typeof input == "string") {
            for (local i = 0; i< input.len(); i++) {
                byteArray.append(input[i].tointeger() & 0xFF);
            }
        } else {
            // 假设是数组，直接使用
            byteArray = input;
        }

        local inputLength = byteArray.len();
        local i = 0;
        local j = 0;
        local charArray3 = array(3);
        local charArray4 = array(4);
        local encoded = "";

        // 处理每3个字节为一组
        local pos = 0;
        while (pos< inputLength) {
            charArray3[i++] = byteArray[pos++];

            if (i == 3) {
                // 将3个字节转换为4个base64字符
                charArray4[0] = (charArray3[0] & 0xfc) >> 2;
                charArray4[1] = ((charArray3[0] & 0x03) << 4) + ((charArray3[1] & 0xf0) >> 4);
                charArray4[2] = ((charArray3[1] & 0x0f) << 2) + ((charArray3[2] & 0xc0) >> 6);
                charArray4[3] = charArray3[2] & 0x3f;

                for (i = 0; i< 4; i++) {
                    encoded += base64_chars.slice(charArray4[i], charArray4[i] + 1);
                }
                i = 0;
            }
        }

        // 处理剩余的字节（不足3个字节的情况）
        if (i > 0) {
            for (j = i; j< 3; j++) {
                charArray3[j] = 0;
            }

            charArray4[0] = (charArray3[0] & 0xfc) >> 2;
            charArray4[1] = ((charArray3[0] & 0x03) << 4) + ((charArray3[1] & 0xf0) >> 4);
            charArray4[2] = ((charArray3[1] & 0x0f) << 2) + ((charArray3[2] & 0xc0) >> 6);
            charArray4[3] = charArray3[2] & 0x3f;

            for (j = 0; j< i + 1; j++) {
                encoded += base64_chars.slice(charArray4[j], charArray4[j] + 1);
            }

            // 添加填充字符 '='
            while (i++<3) {
                encoded += "=";
            }
        }

        return encoded;
    }


    function GetFile(FileName) {
        local Io = IO(FileName, "r+");

        local Ctx = Memory.alloc(0x100);
        MD5.MD5_Init(Ctx.C_Object);

        while (true) {
            local Buffer = Memory.alloc(0x1000);
            local Res = Io.ReadBuffer(0x1000);
            if (Res.count == 0) break;
            MD5.MD5_Update(Ctx.C_Object, Memory.allocUtf8String(Res.str).C_Object, Res.count);
        }

        local Result = Memory.alloc(16);
        MD5.MD5_Final(Result.C_Object, Ctx.C_Object);
        Io.Close();
        return base64_encode(Result.readUtf8String(16));
    }
}