您的位置:首页 > 教育 > 锐评 > libidn库下载、编译、示例:实现UTF-8转Punycode、Punycode转UTF-8

libidn库下载、编译、示例:实现UTF-8转Punycode、Punycode转UTF-8

2024/10/6 0:26:39 来源:https://blog.csdn.net/qq_39792001/article/details/142314909  浏览:    关键词:libidn库下载、编译、示例:实现UTF-8转Punycode、Punycode转UTF-8

1 Punycode 编码

1.1 Punycode 编码

一种用于将Unicode字符转换为ASCII字符的编码方式,主要用于实现国际化域名(IDN)。由于域名系统最初只能支持ASCII字符,Punycode允许非ASCII字符的域名通过特定编码方式转换为有效的ASCII域名。

1.2 ASCII、Unicode、UTF-8、UTF-16、UTF-32、GBK和 Punycode编码区别

	ASCII、Unicode、UTF-8、UTF-16、UTF-32、GBK和Punycode都是用于字符编码的系统,它们的目的是将字符映射为计算机可以处理的数字。

1.2.1 ASCII编码

ASCII(American Standard Code for Information Interchange,美国信息交换标准代码)是最早的字符编码系统之一,它使用7位二进制数来表示128个不同的字符,包括大小写英文字母、数字、标点符号以及一些控制字符。

1.2.2 Unicode编码

Unicode是一种旨在为世界上所有字符提供唯一编号的字符编码标准。它包含了几乎所有书写系统中的符号和标点,支持从古代文字到现代字符的广泛字符集。

1.2.3 UTF-8、UTF-16和UTF-32编码

UTF-8、UTF-16和UTF-32是Unicode字符集的编码方式。
1、UTF-8是一种变长的编码方式,使用1到4个字节来表示一个字符,兼容ASCII编码,对英文字符使用单字节表示,而对其他字符则使用更多的字节。
2、UTF-16使用2个或4个字节表示一个字符,对于基本多文种平面(BMP)内的字符使用2个字节,对于辅助平面内的字符使用4个字节。
3、UTF-32使用固定长度的4个字节表示每个字符。

1.2.4 GBK

GBK(Chinese Internal Code Specification)是一种扩展的双字节编码,主要用于简体中文,它是对GB2312编码的扩展,包含了更多汉字和字符。

2 libidn库的下载、编译、转换实例

2.1 ibidn库的下载

libidn下载地址
当前最新的稳定版本为:libidn2-2.3.7.tar.gz

2.2 ibidn库的编译

2.2.1 libidn库的当前主机编译安装

(1) ./configure
(2) make
(3) make install (注:如果不指定prefix,默认安装在/usr/local/下)

2.2.2 libidn库的交叉编译

3 使用libidn库实现utf-8与Punycode相互转换的实例

#include <stdio.h>  
#include <stdlib.h>  
#include <idn2.h>
#include <string.h>#define is_split_symbol(c)	((c) == '.' )int countCharInString(char *str, char ch) {  int count = 0; // 初始化计数器 char *p = str;while (*p) { // 遍历字符串直到遇到字符串结束符'\0'  if (*p == ch) { // 如果当前字符是目标字符  count++; // 计数器加1  }  p++; // 移动到字符串的下一个字符  }  return count; // 返回计数结果  
}static char para[128][64];
static int	npara;
static int domain_para_parse(char *str)
{char *cur;int argcc = 0, i = 0;if (str == NULL) return 0;memset(para, 0, sizeof(para));npara = 0;cur = str;while(is_split_symbol(*cur)) cur++;while (1) {if (*cur == 0) break;if (!is_split_symbol(*cur)){para[npara][argcc] = *cur;argcc ++; cur ++;if (argcc == 64) return 0;//域名关键字超出限制} else {while (is_split_symbol(*cur)) cur++;if (argcc == 64) return 0;//域名关键字超出限制para[npara][argcc] = 0;npara ++; argcc = 0;}if (argcc >= 64) return 0; //域名关键字超出限制//Begin li_xiaofei@topsec.com.cn 20061027if (npara>128) return 0;//域名深度超出限制//End    li_xiaofei@topsec.com.cn 20061027		}if (!is_split_symbol(str[strlen(str)-1])) npara ++;//Begin li_xiaofei@topsec.com.cn 20061027if (npara > 128) return 0;//End    li_xiaofei@topsec.com.cn 20070127return 1;
}int punycode_encode(char *in_str, char **out_str) {char *ascii_domain = NULL,  *p = NULL; // 用于存储转换后的 ASCII 域名  int ret = 0, i = 0;int flags = 0; // 转换标志,当前设置为 0  printf("[%s:%d] in_str %s\n", __func__, __LINE__, in_str);ret = domain_para_parse(in_str);if (!ret) {return -1;}*out_str = p = malloc(npara * 64 * 4 + 1);for ( i = 0; i < npara; i++) {printf("[%s:%d] para[%d] %s\n", __func__, __LINE__, i, para[i]);if (i) {p += sprintf(p, ".");}ret = idn2_to_ascii_8z(para[i], &ascii_domain, flags);  if (ret != IDN2_OK) {  // 如果转换失败,则打印错误信息  fprintf(stderr, "Error converting UTF-8 to ASCII: %d\n", ret);  return -1;  }  p += sprintf(p, "%s", ascii_domain);if (ascii_domain) free(ascii_domain);printf("[%s:%d] out_str %s\n", __func__, __LINE__, *out_str);}printf("[%s:%d] out_str %s\n", __func__, __LINE__, *out_str);return 0;
}int punycode_decode(char * in_str, char **out_str) {char *unicode_domain = NULL,  *p = NULL; // 用于存储转换后的 unicode 域名  int ret = 0, i = 0;int flags = 0; // 转换标志,当前设置为 0  printf("[%s:%d] in_str %s\n", __func__, __LINE__, in_str);ret = domain_para_parse(in_str);if (!ret) {return -1;}*out_str = p = malloc(npara * 64 * 4 + 1);for ( i = 0; i < npara; i++) {printf("[%s:%d] para[%d] %s\n", __func__, __LINE__, i, para[i]);if (i) {p += sprintf(p, ".");}ret = idn2_to_unicode_8z8z(para[i], &unicode_domain, flags);if (ret != IDN2_OK) {  // 如果转换失败,则打印错误信息  fprintf(stderr, "Error converting UTF-8 to ASCII: %d\n", ret);  return -1;  }  p += sprintf(p, "%s", unicode_domain);if (unicode_domain) free(unicode_domain);printf("[%s:%d] out_str %s\n", __func__, __LINE__, *out_str);}printf("[%s:%d] out_str %s\n", __func__, __LINE__, *out_str);
}int main() {  //char utf8_domain[1024] = {0}; // UTF-8 编码的国际化域名 char *utf8_domain = "你好.com.你好.cn"; // UTF-8 编码的国际化域名 char *ascii_domain = NULL; // 用于存储转换后的 ASCII 域名  char *unicode_domain = NULL; // 用于存储转换后的 unicode 域名  int ret = 0;ret = punycode_encode(utf8_domain, &ascii_domain);if (ret < 0) {printf("[%s:%d] %s punycode encode failed!\n", __func__, __LINE__, utf8_domain);goto out;}printf("[%s:%d] ascii_domain %s\n", __func__, __LINE__, ascii_domain);ret = punycode_decode(ascii_domain, &unicode_domain);if (ret < 0) {printf("[%s:%d] %s punycode_decode failed!\n", __func__, __LINE__, ascii_domain);goto out;}printf("[%s:%d] unicode_domain %s\n", __func__, __LINE__, unicode_domain);out:// 释放由 idn2_to_ascii_8z 分配的内存  if (ascii_domain) free(ascii_domain);  if (unicode_domain) free(unicode_domain);  return ret;  
}

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com