You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

ICU的IDNA/Punycode API默认不转换纯ASCII域名大小写?如何解决?

让libicu对纯ASCII域名执行小写转换的解决方案

问题重现

测试程序使用libicu的uidna_IDNToASCII函数对Unicode域名进行Punycode编码,测试结果如下:

$ g++ -std=c++11 -W -Wall test.cpp -licucore
$ ./a.out EXAMΠLE.com
xn--examle-s0e.com
$ ./a.out EXAMPLE.com
EXAMPLE.com

带希腊字母的域名会被转成小写后编码为Punycode,但纯ASCII的EXAMPLE.com输出保持原大写,未执行小写转换。

原因分析

libicu的uidna_IDNToASCII函数遵循IDNA规范:当输入包含非ASCII字符时,会先将域名转换为小写再进行Punycode编码;但对于纯ASCII域名,函数默认认为其符合域名格式要求,不会额外处理大小写转换。

解决方案

在调用uidna_IDNToASCII之前,使用libicu的u_strToLower函数将输入字符串统一转换为小写,无论输入是否包含非ASCII字符。

修改后的完整代码如下:

#include <cstdio>
#include <string>
#include <unicode/uidna.h>
#include <unicode/ustring.h>
#include <vector>
#include <cassert>

std::string convert_utf8_to_idna(const std::string& input) {
    UErrorCode err = U_ZERO_ERROR;
    std::int32_t needed = 0;

    // 将UTF-8转换为UChar
    auto src = std::vector<UChar>(1000);
    (void)u_strFromUTF8WithSub(
        src.data(), src.size(), &needed,
        input.data(), input.size(),
        0xFFFD, nullptr, &err
    );
    src.resize(needed);
    assert(err == U_ZERO_ERROR);

    // 统一转换为小写
    std::vector<UChar> lower_src(src.size());
    u_strToLower(
        lower_src.data(), lower_src.size(),
        src.data(), src.size(),
        nullptr, &err
    );
    assert(err == U_ZERO_ERROR);

    // 执行IDNA编码
    auto dest = std::vector<UChar>(1000);
    needed = uidna_IDNToASCII(
        lower_src.data(), lower_src.size(),
        dest.data(), dest.size(),
        UIDNA_ALLOW_UNASSIGNED, nullptr, &err
    );
    assert(err == U_ZERO_ERROR);
    dest.resize(needed);

    return std::string(dest.begin(), dest.end());
}

int main(int argc, char **argv) {
    std::string input = (argc >= 2) ? argv[1] : "example.com";
    std::string output = convert_utf8_to_idna(input);
    printf("%s\n", output.c_str());
}

测试验证

修改后重新编译运行:

$ g++ -std=c++11 -W -Wall test.cpp -licucore
$ ./a.out EXAMΠLE.com
xn--examle-s0e.com  # 结果不变,依然是小写编码
$ ./a.out EXAMPLE.com
example.com         # 纯ASCII域名现在转为小写输出

内容的提问来源于stack exchange,提问作者Quuxplusone

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.27 05:17:47