10 private const int M_labelLimit = 63;
12 private const int M_defaultNameLimit = 255;
14 private const string M_strAcePrefix =
"xn--";
16 private static char[] M_Dots =
new char[4]
24 private bool m_bAllowUnassigned;
26 private bool m_bUseStd3AsciiRules;
28 private const int punycodeBase = 36;
30 private const int tmin = 1;
32 private const int tmax = 26;
34 private const int skew = 38;
36 private const int damp = 700;
38 private const int initial_bias = 72;
40 private const int initial_n = 128;
42 private const char delimiter =
'-';
44 private const int maxint = 134217727;
46 private const int IDN_ALLOW_UNASSIGNED = 1;
48 private const int IDN_USE_STD3_ASCII_RULES = 2;
50 private const int ERROR_INVALID_NAME = 123;
59 return m_bAllowUnassigned;
63 m_bAllowUnassigned = value;
74 return m_bUseStd3AsciiRules;
78 m_bUseStd3AsciiRules = value;
111 return GetAscii(unicode, index, unicode.Length - index);
127 public string GetAscii(
string unicode,
int index,
int count)
133 if (index < 0 || count < 0)
137 if (index > unicode.Length)
141 if (index > unicode.Length - count)
145 unicode = unicode.Substring(index, count);
148 return GetAsciiUsingOS(unicode);
154 if (unicode[unicode.Length - 1] <=
'\u001f')
158 bool flag = unicode.Length > 0 && IsDot(unicode[unicode.Length - 1]);
160 if (!flag && unicode.Length > 0 && IsDot(unicode[unicode.Length - 1]))
166 ValidateStd3AndAscii(unicode, bUseStd3:
true, bCheckAscii:
false);
168 return punycode_encode(unicode);
171 [SecuritySafeCritical]
172 private string GetAsciiUsingOS(
string unicode)
174 if (unicode.Length == 0)
178 if (unicode[unicode.Length - 1] ==
'\0')
183 int num = IdnToAscii(dwFlags, unicode, unicode.Length,
null, 0);
187 if (lastWin32Error == 123)
189 throw new ArgumentException(Environment.GetResourceString(
"Argument_IdnIllegalName"),
"unicode");
191 throw new ArgumentException(Environment.GetResourceString(
"Argument_InvalidCharSequenceNoIndex"),
"unicode");
193 char[] array =
new char[num];
194 num = IdnToAscii(dwFlags, unicode, unicode.Length, array, num);
198 if (lastWin32Error == 123)
200 throw new ArgumentException(Environment.GetResourceString(
"Argument_IdnIllegalName"),
"unicode");
202 throw new ArgumentException(Environment.GetResourceString(
"Argument_InvalidCharSequenceNoIndex"),
"unicode");
204 return new string(array, 0, num);
236 return GetUnicode(ascii, index, ascii.Length - index);
258 if (index < 0 || count < 0)
262 if (index > ascii.Length)
266 if (index > ascii.Length - count)
270 if (count > 0 && ascii[index + count - 1] ==
'\0')
274 ascii = ascii.Substring(index, count);
277 return GetUnicodeUsingOS(ascii);
279 string text = punycode_decode(ascii);
287 [SecuritySafeCritical]
288 private string GetUnicodeUsingOS(
string ascii)
291 int num = IdnToUnicode(dwFlags, ascii, ascii.Length,
null, 0);
295 if (lastWin32Error == 123)
301 char[] array =
new char[num];
302 num = IdnToUnicode(dwFlags, ascii, ascii.Length, array, num);
306 if (lastWin32Error == 123)
308 throw new ArgumentException(Environment.GetResourceString(
"Argument_IdnIllegalName"),
"ascii");
310 throw new ArgumentException(Environment.GetResourceString(
"Argument_IdnBadPunycode"),
"ascii");
312 return new string(array, 0, num);
322 if (idnMapping !=
null)
324 if (m_bAllowUnassigned == idnMapping.m_bAllowUnassigned)
326 return m_bUseStd3AsciiRules == idnMapping.m_bUseStd3AsciiRules;
337 return (m_bAllowUnassigned ? 100 : 200) + (m_bUseStd3AsciiRules ? 1000 : 2000);
340 private static bool IsSupplementary(
int cTest)
342 return cTest >= 65536;
345 private static bool IsDot(
char c)
347 if (c !=
'.' && c !=
'。' && c !=
'.')
354 private static bool ValidateStd3AndAscii(
string unicode,
bool bUseStd3,
bool bCheckAscii)
356 if (unicode.Length == 0)
358 throw new ArgumentException(Environment.GetResourceString(
"Argument_IdnBadLabelSize"),
"unicode");
361 for (
int i = 0; i < unicode.Length; i++)
363 if (unicode[i] <=
'\u001f')
365 throw new ArgumentException(Environment.GetResourceString(
"Argument_InvalidCharSequence", i),
"unicode");
367 if (bCheckAscii && unicode[i] >=
'\u007f')
371 if (IsDot(unicode[i]))
375 throw new ArgumentException(Environment.GetResourceString(
"Argument_IdnBadLabelSize"),
"unicode");
379 throw new ArgumentException(Environment.GetResourceString(
"Argument_IdnBadLabelSize"),
"Unicode");
381 if (bUseStd3 && i > 0)
383 ValidateStd3(unicode[i - 1], bNextToDot:
true);
389 ValidateStd3(unicode[i], i == num + 1);
392 if (num == -1 && unicode.Length > 63)
394 throw new ArgumentException(Environment.GetResourceString(
"Argument_IdnBadLabelSize"),
"unicode");
396 if (unicode.Length > 255 - ((!IsDot(unicode[unicode.Length - 1])) ? 1 : 0))
398 throw new ArgumentException(Environment.GetResourceString(
"Argument_IdnBadNameSize", 255 - ((!IsDot(unicode[unicode.Length - 1])) ? 1 : 0)),
"unicode");
400 if (bUseStd3 && !IsDot(unicode[unicode.Length - 1]))
402 ValidateStd3(unicode[unicode.Length - 1], bNextToDot:
true);
407 private static void ValidateStd3(
char c,
bool bNextToDot)
414 if ((c <
'[' || c >
'`') && (c <
'{' || c >
'\u007f') && (c !=
'-' || !bNextToDot))
430 throw new ArgumentException(Environment.GetResourceString(
"Argument_IdnBadStd3", c),
"Unicode");
433 private static bool HasUpperCaseFlag(
char punychar)
437 return punychar <=
'Z';
442 private static bool basic(uint cp)
447 private static int decode_digit(
char cp)
449 if (cp >=
'0' && cp <=
'9')
453 if (cp >=
'a' && cp <=
'z')
457 if (cp >=
'A' && cp <=
'Z')
461 throw new ArgumentException(Environment.GetResourceString(
"Argument_IdnBadPunycode"),
"ascii");
464 private static char encode_digit(
int d)
468 return (
char)(d - 26 + 48);
470 return (
char)(d + 97);
473 private static char encode_basic(
char bcp)
475 if (HasUpperCaseFlag(bcp))
477 bcp = (char)(bcp + 32);
482 private static int adapt(
int delta,
int numpoints,
bool firsttime)
484 delta = (firsttime ? (delta / 700) : (delta / 2));
485 delta += delta / numpoints;
492 return (
int)(num + 36 * delta / (delta + 38));
495 private static string punycode_encode(
string unicode)
497 if (unicode.Length == 0)
499 throw new ArgumentException(Environment.GetResourceString(
"Argument_IdnBadLabelSize"),
"unicode");
505 while (num < unicode.Length)
507 num = unicode.IndexOfAny(M_Dots, num2);
510 num = unicode.Length;
514 if (num == unicode.Length)
518 throw new ArgumentException(Environment.GetResourceString(
"Argument_IdnBadLabelSize"),
"unicode");
520 stringBuilder.
Append(
"xn--");
522 BidiCategory bidiCategory = CharUnicodeInfo.GetBidiCategory(unicode, num2);
523 if (bidiCategory == BidiCategory.RightToLeft || bidiCategory == BidiCategory.RightToLeftArabic)
527 if (
char.IsLowSurrogate(unicode, num4))
531 bidiCategory = CharUnicodeInfo.GetBidiCategory(unicode, num4);
532 if (bidiCategory != BidiCategory.RightToLeft && bidiCategory != BidiCategory.RightToLeftArabic)
534 throw new ArgumentException(Environment.GetResourceString(
"Argument_IdnBadBidi"),
"unicode");
538 for (
int i = num2; i < num; i++)
540 BidiCategory bidiCategory2 = CharUnicodeInfo.GetBidiCategory(unicode, i);
541 if (flag && bidiCategory2 == BidiCategory.LeftToRight)
543 throw new ArgumentException(Environment.GetResourceString(
"Argument_IdnBadBidi"),
"unicode");
545 if (!flag && (bidiCategory2 == BidiCategory.RightToLeft || bidiCategory2 == BidiCategory.RightToLeftArabic))
547 throw new ArgumentException(Environment.GetResourceString(
"Argument_IdnBadBidi"),
"unicode");
549 if (basic(unicode[i]))
551 stringBuilder.
Append(encode_basic(unicode[i]));
554 else if (
char.IsSurrogatePair(unicode, i))
560 if (num6 == num - num2)
562 stringBuilder.
Remove(num3,
"xn--".Length);
566 if (unicode.Length - num2 >=
"xn--".Length && unicode.Substring(num2,
"xn--".Length).Equals(
"xn--",
StringComparison.OrdinalIgnoreCase))
568 throw new ArgumentException(Environment.GetResourceString(
"Argument_IdnBadPunycode"),
"unicode");
573 stringBuilder.
Append(
'-');
578 while (num5 < num - num2)
581 int num12 = 134217727;
582 for (
int j = num2; j < num; j += ((!IsSupplementary(num11)) ? 1 : 2))
584 num11 =
char.ConvertToUtf32(unicode, j);
585 if (num11 >= num8 && num11 < num12)
590 num9 += (num12 - num8) * (num5 - num7 + 1);
592 for (
int j = num2; j < num; j += ((!IsSupplementary(num11)) ? 1 : 2))
594 num11 =
char.ConvertToUtf32(unicode, j);
607 int num15 = (num14 <= num10) ? 1 : ((num14 >= num10 + 26) ? 26 : (num14 - num10));
612 stringBuilder.
Append(encode_digit(num15 + (num13 - num15) % (36 - num15)));
613 num13 = (num13 - num15) / (36 - num15);
616 stringBuilder.
Append(encode_digit(num13));
617 num10 = adapt(num9, num5 - num7 + 1, num5 == num6);
620 if (IsSupplementary(num12))
630 if (stringBuilder.
Length - num3 > 63)
632 throw new ArgumentException(Environment.GetResourceString(
"Argument_IdnBadLabelSize"),
"unicode");
634 if (num != unicode.Length)
636 stringBuilder.
Append(
'.');
639 num3 = stringBuilder.
Length;
641 if (stringBuilder.
Length > 255 - ((!IsDot(unicode[unicode.Length - 1])) ? 1 : 0))
643 throw new ArgumentException(Environment.GetResourceString(
"Argument_IdnBadNameSize", 255 - ((!IsDot(unicode[unicode.Length - 1])) ? 1 : 0)),
"unicode");
648 private static string punycode_decode(
string ascii)
650 if (ascii.Length == 0)
652 throw new ArgumentException(Environment.GetResourceString(
"Argument_IdnBadLabelSize"),
"ascii");
654 if (ascii.Length > 255 - ((!IsDot(ascii[ascii.Length - 1])) ? 1 : 0))
656 throw new ArgumentException(Environment.GetResourceString(
"Argument_IdnBadNameSize", 255 - ((!IsDot(ascii[ascii.Length - 1])) ? 1 : 0)),
"ascii");
662 while (num < ascii.Length)
664 num = ascii.IndexOf(
'.', num2);
665 if (num < 0 || num > ascii.Length)
671 if (num == ascii.Length)
675 throw new ArgumentException(Environment.GetResourceString(
"Argument_IdnBadLabelSize"),
"ascii");
679 throw new ArgumentException(Environment.GetResourceString(
"Argument_IdnBadLabelSize"),
"ascii");
681 if (ascii.Length <
"xn--".Length + num2 || !ascii.Substring(num2,
"xn--".Length).Equals(
"xn--",
StringComparison.OrdinalIgnoreCase))
683 stringBuilder.
Append(ascii.Substring(num2, num - num2));
688 int num4 = ascii.LastIndexOf(
'-', num - 1);
691 throw new ArgumentException(Environment.GetResourceString(
"Argument_IdnBadPunycode"),
"ascii");
701 for (
int i = num2; i < num2 + num5; i++)
703 if (ascii[i] >
'\u007f')
705 throw new ArgumentException(Environment.GetResourceString(
"Argument_IdnBadPunycode"),
"ascii");
707 stringBuilder.
Append((
char)((ascii[i] >=
'A' && ascii[i] <=
'Z') ? (ascii[i] - 65 + 97) : ascii[i]));
710 int num6 = num2 + ((num5 > 0) ? (num5 + 1) : 0);
724 throw new ArgumentException(Environment.GetResourceString(
"Argument_IdnBadPunycode"),
"ascii");
726 int num15 = decode_digit(ascii[num6++]);
727 if (num15 > (134217727 - num9) / num12)
729 throw new ArgumentException(Environment.GetResourceString(
"Argument_IdnBadPunycode"),
"ascii");
731 num9 += num15 * num12;
732 int num16 = (num13 <= num8) ? 1 : ((num13 >= num8 + 26) ? 26 : (num13 - num8));
737 if (num12 > 134217727 / (36 - num16))
739 throw new ArgumentException(Environment.GetResourceString(
"Argument_IdnBadPunycode"),
"ascii");
744 num8 = adapt(num9 - num11, stringBuilder.
Length - num3 - num10 + 1, num11 == 0);
745 if (num9 / (stringBuilder.
Length - num3 - num10 + 1) > 134217727 - num7)
747 throw new ArgumentException(Environment.GetResourceString(
"Argument_IdnBadPunycode"),
"ascii");
749 num7 += num9 / (stringBuilder.
Length - num3 - num10 + 1);
750 num9 %= stringBuilder.
Length - num3 - num10 + 1;
751 if (num7 < 0 || num7 > 1114111 || (num7 >= 55296 && num7 <= 57343))
753 throw new ArgumentException(Environment.GetResourceString(
"Argument_IdnBadPunycode"),
"ascii");
755 string value =
char.ConvertFromUtf32(num7);
763 if (num18 >= stringBuilder.
Length)
765 throw new ArgumentException(Environment.GetResourceString(
"Argument_IdnBadPunycode"),
"ascii");
767 if (
char.IsSurrogate(stringBuilder[num18]))
779 stringBuilder.
Insert(num18, value);
780 if (IsSupplementary(num7))
787 BidiCategory bidiCategory = CharUnicodeInfo.GetBidiCategory(stringBuilder.
ToString(), num3);
788 if (bidiCategory == BidiCategory.RightToLeft || bidiCategory == BidiCategory.RightToLeftArabic)
792 for (
int j = num3; j < stringBuilder.
Length; j++)
794 if (!
char.IsLowSurrogate(stringBuilder.
ToString(), j))
796 bidiCategory = CharUnicodeInfo.GetBidiCategory(stringBuilder.
ToString(), j);
797 if ((flag && bidiCategory == BidiCategory.LeftToRight) || (!flag && (bidiCategory == BidiCategory.RightToLeft || bidiCategory == BidiCategory.RightToLeftArabic)))
799 throw new ArgumentException(Environment.GetResourceString(
"Argument_IdnBadBidi"),
"ascii");
803 if (flag && bidiCategory != BidiCategory.RightToLeft && bidiCategory != BidiCategory.RightToLeftArabic)
805 throw new ArgumentException(Environment.GetResourceString(
"Argument_IdnBadBidi"),
"ascii");
810 throw new ArgumentException(Environment.GetResourceString(
"Argument_IdnBadLabelSize"),
"ascii");
812 if (num != ascii.Length)
814 stringBuilder.
Append(
'.');
817 num3 = stringBuilder.
Length;
819 if (stringBuilder.
Length > 255 - ((!IsDot(stringBuilder[stringBuilder.
Length - 1])) ? 1 : 0))
821 throw new ArgumentException(Environment.GetResourceString(
"Argument_IdnBadNameSize", 255 - ((!IsDot(stringBuilder[stringBuilder.
Length - 1])) ? 1 : 0)),
"ascii");
826 [DllImport(
"kernel32.dll",
CharSet =
CharSet.Unicode, SetLastError =
true)]
828 [SuppressUnmanagedCodeSecurity]
829 private static extern int IdnToAscii(uint dwFlags, [In] [MarshalAs(
UnmanagedType.LPWStr)]
string lpUnicodeCharStr,
int cchUnicodeChar, [Out]
char[] lpASCIICharStr,
int cchASCIIChar);
831 [DllImport(
"kernel32.dll",
CharSet =
CharSet.Unicode, SetLastError =
true)]
833 [SuppressUnmanagedCodeSecurity]
834 private static extern int IdnToUnicode(uint dwFlags, [In] [MarshalAs(
UnmanagedType.LPWStr)]
string lpASCIICharStr,
int cchASCIIChar, [Out]
char[] lpUnicodeCharStr,
int cchUnicodeChar);
bool UseStd3AsciiRules
Gets or sets a value that indicates whether standard or relaxed naming conventions are used in operat...
The exception that is thrown when a null reference (Nothing in Visual Basic) is passed to a method th...
string GetUnicode(string ascii)
Decodes a string of one or more domain name labels, encoded according to the IDNA standard,...
unsafe override string ToString()
Converts the value of this instance to a T:System.String.
string GetAscii(string unicode, int index, int count)
Encodes the specified number of characters in a substring of domain name labels that include Unicode ...
override int GetHashCode()
Returns a hash code for this T:System.Globalization.IdnMapping object.
unsafe StringBuilder Insert(int index, string value, int count)
Inserts one or more copies of a specified string into this instance at the specified character positi...
StringComparison
Specifies the culture, case, and sort rules to be used by certain overloads of the M:System....
The exception that is thrown when the value of an argument is outside the allowable range of values a...
string GetAscii(string unicode)
Encodes a string of domain name labels that consist of Unicode characters to a string of displayable ...
Provides information about, and means to manipulate, the current environment and platform....
StringBuilder Append(char value, int repeatCount)
Appends a specified number of copies of the string representation of a Unicode character to this inst...
string GetAscii(string unicode, int index)
Encodes a substring of domain name labels that include Unicode characters outside the US-ASCII charac...
NormalizationForm
Defines the type of normalization to perform.
UnmanagedType
Identifies how to marshal parameters or fields to unmanaged code.
int Length
Gets or sets the length of the current T:System.Text.StringBuilder object.
Provides a collection of methods for allocating unmanaged memory, copying unmanaged memory blocks,...
CharSet
Dictates which character set marshaled strings should use.
Represents a mutable string of characters. This class cannot be inherited.To browse the ....
The exception that is thrown when one of the arguments provided to a method is not valid.
bool AllowUnassigned
Gets or sets a value that indicates whether unassigned Unicode code points are used in operations per...
string GetUnicode(string ascii, int index, int count)
Decodes a substring of a specified length that contains one or more domain name labels,...
Supports the use of non-ASCII characters for Internet domain names. This class cannot be inherited.
static int GetLastWin32Error()
Returns the error code returned by the last unmanaged function that was called using platform invoke ...
string GetUnicode(string ascii, int index)
Decodes a substring of one or more domain name labels, encoded according to the IDNA standard,...
override bool Equals(object obj)
Indicates whether a specified object and the current T:System.Globalization.IdnMapping object are equ...
StringBuilder Remove(int startIndex, int length)
Removes the specified range of characters from this instance.