dclib-punycode.c 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209
  1. /***************************************************************************
  2. * *
  3. * _____ ____ *
  4. * | __ \ / __ \ _ _ _____ *
  5. * | | \ \ / / \_\ | | | | _ \ *
  6. * | | \ \| | | | | | |_| | *
  7. * | | | || | | | | | ___/ *
  8. * | | / /| | __ | | | | _ \ *
  9. * | |__/ / \ \__/ / | |___| | |_| | *
  10. * |_____/ \____/ |_____|_|_____/ *
  11. * *
  12. * Wiimms source code library *
  13. * *
  14. ***************************************************************************
  15. * *
  16. * Copyright (c) 2012-2022 by Dirk Clemens <wiimm@wiimm.de> *
  17. * *
  18. ***************************************************************************
  19. * *
  20. * This library is free software; you can redistribute it and/or modify *
  21. * it under the terms of the GNU General Public License as published by *
  22. * the Free Software Foundation; either version 2 of the License, or *
  23. * (at your option) any later version. *
  24. * *
  25. * This library is distributed in the hope that it will be useful, *
  26. * but WITHOUT ANY WARRANTY; without even the implied warranty of *
  27. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
  28. * GNU General Public License for more details. *
  29. * *
  30. * See file gpl-2.0.txt or http://www.gnu.org/licenses/gpl-2.0.txt *
  31. * *
  32. ***************************************************************************/
  33. #include "dclib-basics.h"
  34. #include "dclib-utf8.h"
  35. #include "dclib-punycode.h"
  36. #include <limits.h>
  37. #include "dclib-punycode.inc"
  38. //
  39. ///////////////////////////////////////////////////////////////////////////////
  40. /////////////// Domain2UTF8() ///////////////
  41. ///////////////////////////////////////////////////////////////////////////////
  42. uint Domain2UTF8
  43. (
  44. // returns the number of scanned bytes of 'source' or 0 on error
  45. char *buf, // valid destination buffer
  46. int buf_size, // size of 'buf' >= 4
  47. const void *source, // NULL or UTF-8 domain to translate
  48. int source_len // length of 'source'; if <0: use strlen(source)
  49. )
  50. {
  51. DASSERT(buf)
  52. DASSERT(source||!source_len);
  53. if ( buf_size < 4 || !source )
  54. return 0;
  55. if ( source_len < 0 )
  56. source_len = strlen(source);
  57. ccp src = source, src_end = source + source_len;
  58. char *buf_ptr = buf, *buf_end = buf + buf_size - 2;
  59. enum { MAX_LEN = 1000 };
  60. char name[MAX_LEN+10];
  61. punycode_uint pname[MAX_LEN+2];
  62. MARK_USED(name,pname);
  63. while ( src < src_end )
  64. {
  65. while ( buf_ptr < buf_end && src < src_end && *src == '.' )
  66. *buf_ptr++ = *src++;
  67. if ( buf_ptr >= buf_end )
  68. {
  69. if (!src)
  70. goto error;
  71. break;
  72. }
  73. if ( src >= src_end )
  74. break;
  75. ccp point = strchr(src,'.');
  76. if (!point)
  77. point = src_end;
  78. if ( src+4 > src_end || memcmp(src,"xn--",4 ))
  79. buf_ptr = StringCopyEM(buf_ptr,buf_end,src,point-src);
  80. else
  81. {
  82. src += 4;
  83. punycode_uint olen = MAX_LEN;
  84. const enum punycode_status stat
  85. = punycode_decode(point-src,src,&olen,pname,0);
  86. char *dest = name;
  87. if ( stat != punycode_success )
  88. dest = name + snprintf(name,sizeof(name),"!ERR=%d",stat);
  89. else
  90. {
  91. punycode_uint *src = pname, *src_end = pname + olen;
  92. char *dest_end = name + MAX_LEN;
  93. while ( src < src_end && dest < dest_end )
  94. dest = PrintUTF8Char(dest,*src++);
  95. *dest = 0;
  96. }
  97. buf_ptr = StringCopyEM(buf_ptr,buf_end,name,dest-name);
  98. }
  99. src = point;
  100. }
  101. *buf_ptr = 0;
  102. return src - (ccp)source;
  103. error:
  104. *buf = 0;
  105. return 0;
  106. }
  107. //
  108. ///////////////////////////////////////////////////////////////////////////////
  109. /////////////// Domain2ASCII() ///////////////
  110. ///////////////////////////////////////////////////////////////////////////////
  111. uint Domain2ASCII
  112. (
  113. // returns the number of scanned bytes of 'source' or 0 on error
  114. char *buf, // valid destination buffer
  115. int buf_size, // size of 'buf' >= 5
  116. const void *source, // NULL or ASCII domain to translate
  117. int source_len // length of 'source'; if <0: use strlen(source)
  118. )
  119. {
  120. DASSERT(buf)
  121. DASSERT(source||!source_len);
  122. if ( buf_size < 5 || !source )
  123. return 0;
  124. if ( source_len < 0 )
  125. source_len = strlen(source);
  126. ccp src = source, src_end = source + source_len;
  127. char *buf_ptr = buf, *buf_end = buf + buf_size - 5;
  128. enum { MAX_LEN = 1000 };
  129. char name[MAX_LEN+10];
  130. punycode_uint pname[MAX_LEN+2];
  131. while ( src < src_end )
  132. {
  133. while ( buf_ptr < buf_end && src < src_end && *src == '.' )
  134. *buf_ptr++ = *src++;
  135. if ( buf_ptr >= buf_end )
  136. {
  137. if (!src)
  138. goto error;
  139. break;
  140. }
  141. if ( src >= src_end )
  142. break;
  143. ccp point = strchr(src,'.');
  144. if (!point)
  145. point = src_end;
  146. punycode_uint *dest = pname, *dest_end = pname + MAX_LEN;
  147. while ( dest < dest_end && src < point )
  148. {
  149. u32 code = ScanUTF8AnsiCharE(&src,point);
  150. *dest++ = code;
  151. }
  152. punycode_uint olen = MAX_LEN;
  153. const enum punycode_status stat =
  154. punycode_encode(dest-pname,pname,0,&olen,name);
  155. if (stat)
  156. goto error;
  157. if ( olen > 0 && name[olen-1] == '-' )
  158. buf_ptr = StringCopyEM(buf_ptr,buf_end,name,olen-1);
  159. else
  160. {
  161. name[olen] = 0;
  162. buf_ptr = StringCat2E(buf_ptr,buf_end,"xn--",name);
  163. }
  164. }
  165. *buf_ptr = 0;
  166. return src - (ccp)source;
  167. error:
  168. *buf = 0;
  169. return 0;
  170. }
  171. //
  172. ///////////////////////////////////////////////////////////////////////////////
  173. /////////////// E N D ///////////////
  174. ///////////////////////////////////////////////////////////////////////////////