2版权所有(C)2002-2024 Simon Josefsson
6GNU Libidn是自由软件:你可以重新发布它和/或
9*由Free发布的GNU Lesser General Public License
26您应该已经收到GNU通用公共许可证的副本,并且
27GNU Lesser通用公共许可证以及本程序。如果
28不是,请参阅<https://www.gnu.org/licenses网站/>. */
44#定义DOTP(c)((c)==0x002E||(c)==0x3002||\
45(c)==0xFF0E||(c)==0xFF61)
51*@in:带有unicode代码点的输入数组。
52*@inlen:带有unicode代码点的输入数组的长度。
53*@out:输出以零结尾的字符串,该字符串必须有at的空间
55*@flags:#Idna_flags值,例如,%Idna_ALLOW_UNASSIGNED或
56*%IDNA_USE_STD3_ASCII_RULES。
58*ToASCII操作采用一系列Unicode代码点
60ASCII范围内的*点(0..7F)。如果ToASCII成功
63*需要注意的是,ToASCII操作可能会失败。ToASCII码
64*如果任何步骤失败,则失败。如果ToASCII操作的任何步骤
69*ToASCII的输入是一系列代码点,即AllowUnassigned
70*标志和UseSTD3ASCIIRules标志。ToASCII的输出是
73*ToASCII从不改变ASCII中的代码点序列
74*范围开始(尽管可能会失败)。应用ToASCII
78*返回值:成功时返回0,或返回#Idna_rc错误代码。
81idna_to_ascii4i(const uint32_t*in,size_t inlen,char*out,int标志)
84uint32_t*src;/*XXX不需要复制数据? */
90*1。如果序列中的所有代码点都在ASCII范围内(0..7F)
104src=malloc(大小(in[0])*(入口+1));
108memcpy(src,in,sizeof(in[0])*入口);
116*2.执行[NAMEPREP]中指定的步骤,如果有则失败
117*错误。[NAMEPREP]中使用了AllowUnassigned标志。
123p=字符串rep_ucs4_to_utf8(in,(ssize_t)inlen,NULL,NULL);
132len=2*len+10;/*XXX最好猜猜? */
141if(标志&IDNA_ALLOW_UNASSIGNED)
142rc=字符串rep_nameprep(p,len);
144rc=字符串rep_nameprep_no_unassigned(p,len);
146同时(rc==STRINGPREP_TOO_SMALL_BUFFER);
151返回IDNA_STRINGPREP_ERROR;
154src=字符串rep_utf8_to_ucs4(p,-1,NULL);
164*3.如果设置了UseSTD3ASCIIRules标志,则执行以下检查:
166*(a)验证无非LDH ASCII码点;也就是说,
167*缺少0..2C、2E。。2F、3A。。40、5B。。60和7B。。第7页。
174if(标志&IDNA_USE_STD3_ASCII_RULES)
179如果(src[i]<=0x2C||src[i]==0x2E||src[i]==0x2F||
180(src[i]>=0x3A&&src[i]<=0x40)||
181(src[i]>=0x5B&&src[i]<=0x60)||
182(src[i]>=0x7B&&src[i]<=0x7F)
185返回IDNA_CONTAINS_NON_LDH;
188如果(src[0]==0x002D||(i>0&&src[i-1]==x002D)
191返回IDNA_CONTAINS_MINUS;
196*4.如果序列中的所有代码点都在ASCII范围内
209/*如果要跳到步骤8,请将字符串复制到输出缓冲区*/
218返回IDNA_INVALID_LENGTH;
234对于(i=0;匹配&&i<strlen(IDNA_ACE_PREFIX);i++)
235如果(((uint32_t)IDNA_ACE_PREFIX[i]&0xFF)=src[i])
240返回IDNA_CONTAINS_ACE_PREFIX;
245*6.使用[PUNYCODE]中的编码算法对序列进行编码
248for(len=0;src[len];len++)
251outlen=63-strlen(IDNA_ACE_PREFIX);
252rc=punycode_encode(len,src,NULL,
253&outlen,&out[strlen(IDNA_ACE_PREFIX)]);
254如果(rc!=PUNYCODE_SUCCESS)
257返回IDNA_PUNYCODE_ERROR;
259out[strlen(IDNA_ACE_PREFIX)+outlen]=“\0”;
265memcpy(输出,IDNA_ACE_PREFIX,strlen(IDNA_ACE _PREFIX));
275返回IDNA_INVALID_LENGTH;
280/*ToUnicode()。可能realloc()utf8in。将无条件释放utf8in。 */
282idna_to_unicode内部(字符*utf8in,
283uint32_t*out,size_t*outlen,int标志)
287size_t utf8len=字符串(utf8in)+1;
288size_t addlen=0,addinc=utf8len/10+1;
293*1.如果序列包含ASCII范围之外的任何代码点
294*(0..7F)然后继续执行步骤2,否则跳至步骤3。
310*2.执行[NAMEPREP]中指定的步骤,如果存在
311*错误。(如果此处也执行ToASCII的步骤3,则不会
313*必要。)AllowUnassigned标志用于[NAMEPREP]中。
317char*newp=重新分配(utf8in,utf8len+addlen);
324if(标志&IDNA_ALLOW_UNASSIGNED)
325rc=字符串rep_nameprep(utf8in,utf8len+addlen);
327rc=字符串rep_nameprep_no_unassigned(utf8in,utf8len+addlen);
331同时(rc==STRINGPREP_TOO_SMALL_BUFFER);
336返回IDNA_STRINGPREP_ERROR;
339/*3.验证序列是否以ACE前缀开头,并保存一个
341 * ...ToASCII和ToUnicode操作必须识别ACE
346if(c_strncasemp(utf8in,IDNA_ACE_PREFIX,strlen(IDNA_ACE _PREFIX))= 0)
355内存移动(utf8in,&utf8in[strlen(IDNA_ACE_PREFIX)],
356strlen(utf8in)-strlen(IDNA_ACE_PREFIX)+1);
358/*5.使用[PUNYCODE]中的解码算法解码序列
365rc=punycode_decode(字符串(utf8in),utf8in.,outlen,out,NULL);
366如果(rc!=PUNYCODE_SUCCESS)
369返回IDNA_PUNYCODE_ERROR;
377rc=idna_to_ascii_4i(out,*outlen,tmpout,flags);
384/*7.验证步骤6的结果是否与保存的副本匹配
388if(c_strcasecmp(utf8in,tmpout+strlen(IDNA_ACE_PREFIX))= 0)
391返回IDNA_ROUNDTRIP_VERIFY_ERROR;
402*idna_to_unicode _ 44i:
403*@in:带有unicode代码点的输入数组。
404*@inlen:带有unicode代码点的输入数组的长度。
405*@out:带有unicode代码点的输出数组。
406*@outlen:在输入时,具有unicode代码点的输出数组的最大大小,
407*退出时,带有unicode代码点的输出数组的实际大小。
408*@flags:#Idna_flags值,例如,%Idna_ALLOW_UNASSIGNED或
409*%IDNA_USE_STD3_ASCII_RULES。
411*ToUnicode操作采用一系列Unicode代码点
413*代码点。如果输入序列是ACE形式的标签,则
417*ToUnicode从未失败。如果任何步骤失败,则原始输入
420*Punycode解码器输出的代码点永远不会超过它
421*输入,但Nameprep可以,因此ToUnicode可以。请注意
426*AllowUnassigned标志和UseSTD3ASCIIRules标志。的输出
427*ToUnicode始终是一系列Unicode代码点。
429*返回值:返回#Idna_rc错误条件,但必须是
432*规范(sans-malloc引起的错误)。注意!这意味着
437idna_to_unicode _44i(常量uint32_t*in,大小_入口,
438uint32_t*out,size_t*outlen,int标志)
441size_t outlensave=*outlen;
444p=字符串rep_ucs4_to_utf8(in,(ssize_t)入口,NULL,NULL);
448rc=idna_to_unicode内部(p,out,outlen,flags);
451memcpy(输出、输入、大小(输入[0])*(输入<输出保存?
456/*p在idna_to_unicode_internal中被释放。 */
465*@input:以零结尾的输入Unicode字符串。
466*@output:指向新分配的输出字符串的指针。
467*@flags:#Idna_flags值,例如,%Idna_ALLOW_UNASSIGNED或
468*%IDNA_USE_STD3_ASCII_RULES。
470*将UCS-4域名转换为ASCII字符串。域名可以
474*返回值:成功时返回%IDNA_SUCCESS,或返回错误代码。
477idna_to_ascii_4z(常量uint32_t*输入,字符**输出,int标志)
487U+3002(表意全停),U+FF0E(全停),
500if(DOTP(输入[0])&&输入[1]==0)
515for(;*end&&!DOTP(*end);结束++)
518if(*end=='\0'&&start==end)
525rc=idna_to_ascii4i(开始,(size_t)(结束-开始),buf,标志);
535size_t l=字符串(输出)+1+字符串(buf)+1;
536char*newp=重新分配(out,l);
564*@input:以零结尾的输入UTF-8字符串。
565*@output:指向新分配的输出字符串的指针。
566*@flags:#Idna_flags值,例如,%Idna_ALLOW_UNASSIGNED或
567*%IDNA_USE_STD3_ASCII_RULES。
569*将UTF-8域名转换为ASCII字符串。域名可以
573*返回值:成功时返回%IDNA_SUCCESS,或返回错误代码。
576idna_to_ascii8z(const char*输入,char**输出,int标志)
582ucs4=字符串rep_utf8_to_ucs4(输入,-1,&ucs4len);
586rc=idna_to_ascii4z(ucs4,输出,标志);
596*@input:在当前语言环境中编码的以零结尾的输入字符串
598*@output:指向新分配的输出字符串的指针。
599*@flags:#Idna_flags值,例如,%Idna_ALLOW_UNASSIGNED或
600*%IDNA_USE_STD3_ASCII_RULES。
602*将区域设置编码中的域名转换为ASCII字符串
606*返回值:成功时返回%IDNA_SUCCESS,或返回错误代码。
609idna_to_ascii_lz(const char*输入,char**输出,int标志)
614utf8=字符串rep_locale_to_utf8(输入);
618rc=idna_to_ascii8z(utf8,输出,标志);
626*idna_to_unicode _4z4z:
627*@input:以零结尾的Unicode字符串。
628*@output:指向新分配的输出Unicode字符串的指针。
629*@flags:#Idna_flags值,例如%Idna_ALLOW_UNASSIGNED或
630*%IDNA_USE_STD3_ASCII_RULES。
632*将UCS-4格式的可能ACE编码域名转换为
637*返回值:成功返回%IDNA_SUCCESS,或返回错误代码。
640idna_to_unicode 4z4z(const uint32_t*输入,uint32-t**输出,int标志)
655for(;*end&&!DOTP(*end);结束++)
658buflen=(size_t)(结束-开始);
659buf=malloc(大小(buf[0])*(buflen+1));
667idna_to_unicode _44i(开始,(size_t)(结束-开始),
672uint32_t*newp=重新分配(out,
682out[outlen++]=0x002E; /* '.'(完全停止)*/
683memcpy(out+outlen,buf,sizeof(buf[0])*buflen);
705*idna_to_unicode _8z4z:
706*@input:以零结尾的UTF-8字符串。
707*@output:指向新分配的输出Unicode字符串的指针。
708*@flags:#Idna_flags值,例如,%Idna_ALLOW_UNASSIGNED或
709*%IDNA_USE_STD3_ASCII_RULES。
711*将UTF-8格式的可能ACE编码域名转换为
716*返回值:成功时返回%IDNA_SUCCESS,或返回错误代码。
719idna_to_unicode 8z4z(const字符*输入,uint32_t**输出,int标志)
725ucs4=字符串rep_utf8_to_ucs4(输入,-1,&ucs4len);
729rc=idna_to_unicode 4z4z(ucs4,输出,标志);
736*idna_to_unicode _8z8z:
737*@input:以零结尾的UTF-8字符串。
738*@output:指向新分配的输出UTF-8字符串的指针。
739*@flags:#Idna_flags值,例如,%Idna_ALLOW_UNASSIGNED或
740*%IDNA_USE_STD3_ASCII_RULES。
742*将UTF-8格式的可能ACE编码域名转换为
747*返回值:成功时返回%IDNA_SUCCESS,或返回错误代码。
750idna_to_unicode 8z8z(const char*输入,char**输出,int标志)
755rc=idna_to_unicode 8z4z(输入,&ucs4,标志);
759*输出=字符串rep_ucs4_to_utf8(ucs4,-1,NULL,NULL);
769*idna_to_unicode_8zlz:
770*@input:以零结尾的UTF-8字符串。
773*@flags:#Idna_flags值,例如,%Idna_ALLOW_UNASSIGNED或
774*%IDNA_USE_STD3_ASCII_RULES。
776*将UTF-8格式的可能ACE编码域名转换为
781*返回值:成功时返回%IDNA_SUCCESS,或返回错误代码。
784idna_to_unicode 8zlz(const char*输入,char**输出,int标志)
789rc=idna_to_unicode 8z8z(输入,&utf8,标志);
793*输出=字符串rep_utf8_to_locale(utf8);
803*idna_to_unicode _ lzlz:
804*@input:在当前语言环境中编码的以零结尾的字符串
808*@flags:#Idna_flags值,例如,%Idna_ALLOW_UNASSIGNED或
809*%IDNA_USE_STD3_ASCII_RULES。
812*设置为在当前语言环境的字符集中编码的字符串。
816*返回值:成功返回%IDNA_SUCCESS,或返回错误代码。
819idna_to_unicode _lzlz(const char*输入,char**输出,int标志)
824utf8=字符串rep_locale_to_utf8(输入);
828rc=idna_to_unicode 8zlz(utf8,输出,标志);
837*IANA分配的用于IDNA的前缀。“xn--”
842*@IDNA_SUCCESS:操作成功。此值保证为
845*@IDNA_STRINGPREP_ERROR:字符串准备期间出错。
846*@IDNA_PUNYCODE_ERROR:PUNYCODE操作期间出错。
847*@IDNA_CONTAINS_NON_LDH:对于IDNA_USE_STD3_ASCII_RULES,表示
849*@IDNA_CONTAINS_LDH:与@IDNA_CONTAINS-NON_LDH相同,以实现兼容性
851*@IDNA_CONTAINS_MINUS:对于IDNA_USE_STD3_ASCII_RULES,表示
852*字符串包含前导或尾随连字符-分钟(U+002D)。
853*@IDNA_INVALID_LENGTH:最终输出字符串不在
855*@IDNA_NO_ACE_PREFIX:字符串不包含ACE前缀
857*@IDNA_ROUNDTRIP_VERIFY_ERROR:输出上的ToASCII操作
859*@IDNA_CONTAINS_ACE_PREFIX:输入包含ACE前缀(用于
861*@IDNA_ICONV_ERROR:字符编码转换错误。
862*@IDNA_MALLOC_ERROR:无法分配缓冲区(这通常是
864*@IDNA_DLOPEN_ERROR:无法DLOPEN libcidn DSO(仅使用
867*idna_to_ascii_4i()的枚举返回码,
868*idna_to_unicode_44i()函数(以及从这些函数派生的函数
876*@IDNA_ALLOW_UNASSIGNED:不要拒绝包含未分配的字符串
878*@IDNA_USE_STD3_ASCII_RULES:根据STD3验证字符串
881*传递给idna_to_ascii_4i()、idna_toSunicode_44i()等的标志。