U_CAPI int32_t U_EXPORT2 uidna_compare( const UChar *s1, int32_t length1, const UChar *s2, int32_t length2, int32_t options, UErrorCode* status){ if(status == NULL || U_FAILURE(*status)){ return -1; } UChar b1Stack[MAX_IDN_BUFFER_SIZE], b2Stack[MAX_IDN_BUFFER_SIZE]; UChar *b1 = b1Stack, *b2 = b2Stack; int32_t b1Len, b2Len, b1Capacity = MAX_IDN_BUFFER_SIZE, b2Capacity = MAX_IDN_BUFFER_SIZE; int32_t result=-1; UParseError parseError; b1Len = uidna_IDNToASCII(s1, length1, b1, b1Capacity, options, &parseError, status); if(*status == U_BUFFER_OVERFLOW_ERROR){ // redo processing of string b1 = (UChar*) uprv_malloc(b1Len * U_SIZEOF_UCHAR); if(b1==NULL){ *status = U_MEMORY_ALLOCATION_ERROR; goto CLEANUP; } *status = U_ZERO_ERROR; // reset error b1Len = uidna_IDNToASCII(s1,length1,b1,b1Len, options, &parseError, status); } b2Len = uidna_IDNToASCII(s2,length2, b2,b2Capacity, options, &parseError, status); if(*status == U_BUFFER_OVERFLOW_ERROR){ // redo processing of string b2 = (UChar*) uprv_malloc(b2Len * U_SIZEOF_UCHAR); if(b2==NULL){ *status = U_MEMORY_ALLOCATION_ERROR; goto CLEANUP; } *status = U_ZERO_ERROR; // reset error b2Len = uidna_IDNToASCII(s2, length2, b2, b2Len, options, &parseError, status); } // when toASCII is applied all label separators are replaced with FULL_STOP result = compareCaseInsensitiveASCII(b1,b1Len,b2,b2Len); CLEANUP: if(b1 != b1Stack){ uprv_free(b1); } if(b2 != b2Stack){ uprv_free(b2); } return result; }
void IdnaConfTest::Call(){ if (type == -1 || option == -1 || passfail == -1 || namebase.isBogus() || namezone.isBogus()){ errln("Incomplete record"); } else { UErrorCode status = U_ZERO_ERROR; UChar result[200] = {0,}; // simple life const UChar *p = namebase.getTerminatedBuffer(); const int p_len = namebase.length(); if (type == 0 && option == 0){ uidna_IDNToASCII(p, p_len, result, 200, UIDNA_USE_STD3_RULES, NULL, &status); } else if (type == 0 && option == 1){ uidna_IDNToASCII(p, p_len, result, 200, UIDNA_ALLOW_UNASSIGNED, NULL, &status); } else if (type == 1 && option == 0){ uidna_IDNToUnicode(p, p_len, result, 200, UIDNA_USE_STD3_RULES, NULL, &status); } else if (type == 1 && option == 1){ uidna_IDNToUnicode(p, p_len, result, 200, UIDNA_ALLOW_UNASSIGNED, NULL, &status); } if (passfail == 0){ if (U_FAILURE(status)){ id.append(" should pass, but failed. - "); id.append(u_errorName(status)); errcheckln(status, id); } else{ if (namezone.compare(result, -1) == 0){ // expected logln(UnicodeString("namebase: ") + prettify(namebase) + UnicodeString(" result: ") + prettify(result)); } else { id.append(" no error, but result is not as expected."); errln(id); } } } else if (passfail == 1){ if (U_FAILURE(status)){ // expected // TODO: Uncomment this when U_IDNA_ZERO_LENGTH_LABEL_ERROR is added to u_errorName //logln("Got the expected error: " + UnicodeString(u_errorName(status))); } else{ if (namebase.compare(result, -1) == 0){ // garbage in -> garbage out logln(UnicodeString("ICU will not recognize malformed ACE-Prefixes or incorrect ACE-Prefixes. ") + UnicodeString("namebase: ") + prettify(namebase) + UnicodeString(" result: ") + prettify(result)); } else { id.append(" should fail, but not failed. "); id.append(u_errorName(status)); errln(id); } } } } type = option = passfail = -1; namebase.setToBogus(); namezone.setToBogus(); id.remove(); return; }
static jstring NativeIDN_convertImpl(JNIEnv* env, jclass, jstring javaSrc, jint flags, jboolean toAscii) { ScopedStringChars src(env, javaSrc); if (src.get() == NULL) { return NULL; } UChar dst[256]; UErrorCode status = U_ZERO_ERROR; size_t resultLength = toAscii ? uidna_IDNToASCII(src.get(), src.size(), &dst[0], sizeof(dst), flags, NULL, &status) : uidna_IDNToUnicode(src.get(), src.size(), &dst[0], sizeof(dst), flags, NULL, &status); if (U_FAILURE(status)) { jniThrowException(env, "java/lang/IllegalArgumentException", u_errorName(status)); return NULL; } if (!toAscii) { // ICU only translates separators to ASCII for toASCII. // Java expects the translation for toUnicode too. // We may as well do this here, while the string is still mutable. for (size_t i = 0; i < resultLength; ++i) { if (isLabelSeparator(dst[i])) { dst[i] = '.'; } } } return env->NewString(&dst[0], resultLength); }
int WINAPI IdnToAscii ( DWORD dwFlags, LPCWSTR lpUnicodeCharStr, int cchUnicodeChar, LPWSTR lpASCIICharStr, int cchASCIIChar ) { UErrorCode status; int32_t retval = uidna_IDNToASCII ( lpUnicodeCharStr, cchUnicodeChar, lpASCIICharStr, cchASCIIChar, IDNA_FlagsToICU(dwFlags), NULL, &status ); if(U_FAILURE(status)) SetLastError(NLS_ErrorFromICU(status)); return retval; }
static void php_intl_idn_to(INTERNAL_FUNCTION_PARAMETERS, const char *domain, int32_t domain_len, uint32_t option, int mode) { UChar* ustring = NULL; int ustring_len = 0; UErrorCode status; char *converted_utf8; size_t converted_utf8_len; UChar converted[MAXPATHLEN]; int32_t converted_ret_len; /* convert the string to UTF-16. */ status = U_ZERO_ERROR; intl_convert_utf8_to_utf16(&ustring, &ustring_len, domain, domain_len, &status); if (U_FAILURE(status)) { intl_error_set_code(NULL, status); /* Set error messages. */ intl_error_set_custom_msg( NULL, "Error converting input string to UTF-16", 0 ); if (ustring) { efree(ustring); } RETURN_FALSE; } else { UParseError parse_error; status = U_ZERO_ERROR; if (mode == INTL_IDN_TO_ASCII) { converted_ret_len = uidna_IDNToASCII(ustring, ustring_len, converted, MAXPATHLEN, (int32_t)option, &parse_error, &status); } else { converted_ret_len = uidna_IDNToUnicode(ustring, ustring_len, converted, MAXPATHLEN, (int32_t)option, &parse_error, &status); } efree(ustring); if (U_FAILURE(status)) { intl_error_set( NULL, status, "idn_to_ascii: cannot convert to ASCII", 0 ); RETURN_FALSE; } status = U_ZERO_ERROR; intl_convert_utf16_to_utf8(&converted_utf8, &converted_utf8_len, converted, converted_ret_len, &status); if (U_FAILURE(status)) { /* Set global error code. */ intl_error_set_code(NULL, status); /* Set error messages. */ intl_error_set_custom_msg( NULL, "Error converting output string to UTF-8", 0 ); efree(converted_utf8); RETURN_FALSE; } } /* return the allocated string, not a duplicate */ RETVAL_STRINGL(converted_utf8, converted_utf8_len); //???? efree(converted_utf8); }
/* * imp: common/uidna.cpp * hdr: common/unicode/uidna.h * @stable ICU 2.6 */ U_CAPI int32_t U_EXPORT2 uidna_IDNToASCII_4_0( const UChar* src, int32_t srcLength, UChar* dest, int32_t destCapacity, int32_t options, UParseError* parseError, UErrorCode* status) { return uidna_IDNToASCII(src, srcLength, dest, destCapacity, options, parseError, status); }
// Converts the Unicode input representing a hostname to ASCII using IDN rules. // The output must be ASCII, but is represented as wide characters. // // On success, the output will be filled with the ASCII host name and it will // return true. Unlike most other canonicalization functions, this assumes that // the output is empty. The beginning of the host will be at offset 0, and // the length of the output will be set to the length of the new host name. // // On error, this will return false. The output in this case is undefined. bool IDNToASCII(const UChar* src, int sourceLength, URLBuffer<UChar>& output) { ASSERT(!output.length()); // Output buffer is assumed empty. while (true) { // Use ALLOW_UNASSIGNED to be more tolerant of hostnames that violate // the spec (which do exist). This does not present any risk and is a // little more future proof. UErrorCode err = U_ZERO_ERROR; int numConverted = uidna_IDNToASCII(src, sourceLength, output.data(), output.capacity(), UIDNA_ALLOW_UNASSIGNED, 0, &err); if (err == U_ZERO_ERROR) { output.setLength(numConverted); return true; } if (err != U_BUFFER_OVERFLOW_ERROR) return false; // Unknown error, give up. // Not enough room in our buffer, expand. output.resize(output.capacity() * 2); } }
static void TestLength(){ { static const char* cl = "my_very_very_very_very_very_very_very_very_very_very_very_very_very_long_and_incredibly_uncreative_domain_label"; UChar ul[128] = {'\0'}; UChar dest[256] = {'\0'}; /* this unicode string is longer than MAX_LABEL_BUFFER_SIZE and produces an IDNA prepared string (including xn--)that is exactly 63 bytes long */ UChar ul1[] = { 0xC138, 0xACC4, 0xC758, 0xBAA8, 0xB4E0, 0xC0AC, 0xB78C, 0xB4E4, 0xC774, 0xD55C, 0xAD6D, 0xC5B4, 0xB97C, 0xC774, 0x00AD, 0x034F, 0x1806, 0x180B, 0x180C, 0x180D, 0x200B, 0x200C, 0x200D, 0x2060, 0xFE00, 0xFE01, 0xFE02, 0xFE03, 0xFE04, 0xFE05, 0xFE06, 0xFE07, 0xFE08, 0xFE09, 0xFE0A, 0xFE0B, 0xFE0C, 0xFE0D, 0xFE0E, 0xFE0F, 0xFEFF, 0xD574, 0xD55C, 0xB2E4, 0xBA74, 0xC138, 0x0041, 0x00AD, 0x034F, 0x1806, 0x180B, 0x180C, 0x180D, 0x200B, 0x200C, 0x200D, 0x2060, 0xFE00, 0xFE01, 0xFE02, 0xFE03, 0xFE04, 0xFE05, 0xFE06, 0xFE07, 0xFE08, 0xFE09, 0xFE0A, 0xFE0B, 0xFE0C, 0xFE0D, 0xFE0E, 0xFE0F, 0xFEFF, 0x00AD, 0x034F, 0x1806, 0x180B, 0x180C, 0x180D, 0x200B, 0x200C, 0x200D, 0x2060, 0xFE00, 0xFE01, 0xFE02, 0xFE03, 0xFE04, 0xFE05, 0xFE06, 0xFE07, 0xFE08, 0xFE09, 0xFE0A, 0xFE0B, 0xFE0C, 0xFE0D, 0xFE0E, 0xFE0F, 0xFEFF, 0x00AD, 0x034F, 0x1806, 0x180B, 0x180C, 0x180D, 0x200B, 0x200C, 0x200D, 0x2060, 0xFE00, 0xFE01, 0xFE02, 0xFE03, 0xFE04, 0xFE05, 0xFE06, 0xFE07, 0xFE08, 0xFE09, 0xFE0A, 0xFE0B, 0xFE0C, 0xFE0D, 0xFE0E, 0xFE0F, 0xFEFF, 0x0000 }; int32_t len1 = LENGTHOF(ul1)-1/*remove the null termination*/; int32_t destLen = LENGTHOF(dest); UErrorCode status = U_ZERO_ERROR; UParseError ps; int32_t len = (int32_t)strlen(cl); u_charsToUChars(cl, ul, len+1); destLen = uidna_toUnicode(ul, len, dest, destLen, UIDNA_DEFAULT, &ps, &status); if(status != U_ZERO_ERROR){ log_err_status(status, "uidna_toUnicode failed with error %s.\n", u_errorName(status)); } status = U_ZERO_ERROR; destLen = LENGTHOF(dest); len = -1; destLen = uidna_toUnicode(ul, len, dest, destLen, UIDNA_DEFAULT, &ps, &status); if(status != U_ZERO_ERROR){ log_err_status(status, "uidna_toUnicode failed with error %s.\n", u_errorName(status)); } status = U_ZERO_ERROR; destLen = LENGTHOF(dest); len = (int32_t)strlen(cl); destLen = uidna_toASCII(ul, len, dest, destLen, UIDNA_DEFAULT, &ps, &status); if(status != U_IDNA_LABEL_TOO_LONG_ERROR){ log_err_status(status, "uidna_toASCII failed with error %s.\n", u_errorName(status)); } status = U_ZERO_ERROR; destLen = LENGTHOF(dest); len = -1; destLen = uidna_toASCII(ul, len, dest, destLen, UIDNA_DEFAULT, &ps, &status); if(status != U_IDNA_LABEL_TOO_LONG_ERROR){ log_err_status(status, "uidna_toASCII failed with error %s.\n", u_errorName(status)); } status = U_ZERO_ERROR; destLen = LENGTHOF(dest); destLen = uidna_toASCII(ul1, len1, dest, destLen, UIDNA_DEFAULT, &ps, &status); if(status != U_ZERO_ERROR){ log_err_status(status, "uidna_toASCII failed with error %s.\n", u_errorName(status)); } status = U_ZERO_ERROR; destLen = LENGTHOF(dest); len1 = -1; destLen = uidna_toASCII(ul1, len1, dest, destLen, UIDNA_DEFAULT, &ps, &status); if(status != U_ZERO_ERROR){ log_err_status(status, "uidna_toASCII failed with error %s.\n", u_errorName(status)); } } { static const char* cl = "my_very_very_long_and_incredibly_uncreative_domain_label.my_very_very_long_and_incredibly_uncreative_domain_label.my_very_very_long_and_incredibly_uncreative_domain_label.my_very_very_long_and_incredibly_uncreative_domain_label.my_very_very_long_and_incredibly_uncreative_domain_label.my_very_very_long_and_incredibly_uncreative_domain_label.ibm.com"; UChar ul[400] = {'\0'}; UChar dest[400] = {'\0'}; int32_t destLen = LENGTHOF(dest); UErrorCode status = U_ZERO_ERROR; UParseError ps; int32_t len = (int32_t)strlen(cl); u_charsToUChars(cl, ul, len+1); destLen = uidna_IDNToUnicode(ul, len, dest, destLen, UIDNA_DEFAULT, &ps, &status); if(status != U_IDNA_DOMAIN_NAME_TOO_LONG_ERROR){ log_err_status(status, "uidna_IDNToUnicode failed with error %s.\n", u_errorName(status)); } status = U_ZERO_ERROR; destLen = LENGTHOF(dest); len = -1; destLen = uidna_IDNToUnicode(ul, len, dest, destLen, UIDNA_DEFAULT, &ps, &status); if(status != U_IDNA_DOMAIN_NAME_TOO_LONG_ERROR){ log_err_status(status, "uidna_IDNToUnicode failed with error %s.\n", u_errorName(status)); } status = U_ZERO_ERROR; destLen = LENGTHOF(dest); len = (int32_t)strlen(cl); destLen = uidna_IDNToASCII(ul, len, dest, destLen, UIDNA_DEFAULT, &ps, &status); if(status != U_IDNA_DOMAIN_NAME_TOO_LONG_ERROR){ log_err_status(status, "uidna_IDNToASCII failed with error %s.\n", u_errorName(status)); } status = U_ZERO_ERROR; destLen = LENGTHOF(dest); len = -1; destLen = uidna_IDNToASCII(ul, len, dest, destLen, UIDNA_DEFAULT, &ps, &status); if(status != U_IDNA_DOMAIN_NAME_TOO_LONG_ERROR){ log_err_status(status, "uidna_IDNToASCII failed with error %s.\n", u_errorName(status)); } status = U_ZERO_ERROR; uidna_compare(ul, len, ul, len, UIDNA_DEFAULT, &status); if(status != U_IDNA_DOMAIN_NAME_TOO_LONG_ERROR){ log_err_status(status, "uidna_compare failed with error %s.\n", u_errorName(status)); } uidna_compare(ul, -1, ul, -1, UIDNA_DEFAULT, &status); if(status != U_IDNA_DOMAIN_NAME_TOO_LONG_ERROR){ log_err_status(status, "uidna_compare failed with error %s.\n", u_errorName(status)); } } }
static Variant php_intl_idn_to(CStrRef domain, VRefParam errorcode, int mode) { long option = 0; UChar* ustring = NULL; int ustring_len = 0; UErrorCode status; char *converted_utf8 = NULL; int32_t converted_utf8_len; UChar* converted = NULL; int32_t converted_ret_len; // Convert the string to UTF-16 status = U_ZERO_ERROR; intl_convert_utf8_to_utf16(&ustring, &ustring_len, (char*)domain.data(), domain.size(), &status); if (U_FAILURE(status)) { free(ustring); errorcode = status; return false; } // Call the appropriate IDN function int converted_len = (ustring_len > 1) ? ustring_len : 1; for (;;) { UParseError parse_error; status = U_ZERO_ERROR; converted = (UChar*)malloc(sizeof(UChar)*converted_len); // If the malloc failed, bail out if (!converted) { free(ustring); errorcode = U_MEMORY_ALLOCATION_ERROR; return false; } if (mode == INTL_IDN_TO_ASCII) { converted_ret_len = uidna_IDNToASCII(ustring, ustring_len, converted, converted_len, (int32_t)option, &parse_error, &status); } else { converted_ret_len = uidna_IDNToUnicode(ustring, ustring_len, converted, converted_len, (int32_t)option, &parse_error, &status); } if (status != U_BUFFER_OVERFLOW_ERROR) break; // If we have a buffer overflow error, try again with a larger buffer free(converted); converted = NULL; converted_len = converted_len * 2; } free(ustring); if (U_FAILURE(status)) { free(converted); errorcode = status; return false; } // Convert the string back to UTF-8 status = U_ZERO_ERROR; intl_convert_utf16_to_utf8(&converted_utf8, &converted_utf8_len, converted, converted_ret_len, &status); free(converted); if (U_FAILURE(status)) { free(converted_utf8); errorcode = status; return false; } // Return the string return String(converted_utf8, converted_utf8_len, AttachString); }
static char * IDNToASCII(const char *text) // IN { #ifdef HAVE_UIDNA_IDNTOASCII /* * To convert UTF-8 to ASCII, first we need to convert it to UTF-16 * for ICU, then convert it to 16-bit "ASCII", and then back to * 8-bit ASCII (which is ASCII) for xmlParse(). */ long utf16Len; GError *error = NULL; gunichar2 *utf16Text = g_utf8_to_utf16(text, -1, NULL, &utf16Len, &error); if (error) { g_warning("Could not convert text \"%s\" to UTF-16: %s\n", text, error->message); g_error_free(error); return NULL; } int32_t idnLen = 2 * utf16Len; UChar *idnText; UErrorCode status; int32_t len; /* * If we don't allocate enough characters on the first attempt, * IDNToASCII() will return how many characters we need. If the * second attempt fails, just give up rather than looping forever. */ tryConversion: idnText = g_new(UChar, idnLen + 1); status = U_ZERO_ERROR; len = uidna_IDNToASCII((const UChar *)utf16Text, utf16Len, idnText, idnLen, UIDNA_DEFAULT, NULL, &status); if (len > idnLen) { g_free(idnText); // Guard against multiple loops. if (idnLen != 2 * utf16Len) { g_warning("The ASCII length was greater than we allocated after two " "attempts; giving up on \"%s\".", text); g_free(idnText); g_free(utf16Text); return NULL; } idnLen = len; goto tryConversion; } else if (U_FAILURE(status)) { g_warning("Could not convert text \"%s\" to IDN: %s\n", text, u_errorName(status)); g_free(idnText); g_free(utf16Text); return NULL; } // Convert it back to UTF-8/ASCII. char *ret = g_utf16_to_utf8((gunichar2 *)idnText, len, NULL, NULL, NULL); g_free(idnText); g_free(utf16Text); return ret; #else g_assert_not_reached(); return NULL; #endif // HAVE_UIDNA_IDNTOASCII }
static Variant php_intl_idn_to(const String& domain, int64_t options, IdnVariant idn_variant, VRefParam idna_info, int mode) { UChar* ustring = NULL; int ustring_len = 0; UErrorCode status; char *converted_utf8 = NULL; int32_t converted_utf8_len; UChar* converted = NULL; int32_t converted_ret_len; if (idn_variant != INTL_IDN_VARIANT_2003) { #ifdef HAVE_46_API if (idn_variant == INTL_IDN_VARIANT_UTS46) { return php_intl_idn_to_46(domain, options, idn_variant, ref(idna_info), mode); } #endif return false; } // Convert the string to UTF-16 status = U_ZERO_ERROR; intl_convert_utf8_to_utf16(&ustring, &ustring_len, (char*)domain.data(), domain.size(), &status); if (U_FAILURE(status)) { free(ustring); return false; } // Call the appropriate IDN function int converted_len = (ustring_len > 1) ? ustring_len : 1; for (;;) { UParseError parse_error; status = U_ZERO_ERROR; converted = (UChar*)malloc(sizeof(UChar)*converted_len); // If the malloc failed, bail out if (!converted) { free(ustring); return false; } if (mode == INTL_IDN_TO_ASCII) { converted_ret_len = uidna_IDNToASCII(ustring, ustring_len, converted, converted_len, (int32_t)options, &parse_error, &status); } else { converted_ret_len = uidna_IDNToUnicode(ustring, ustring_len, converted, converted_len, (int32_t)options, &parse_error, &status); } if (status != U_BUFFER_OVERFLOW_ERROR) break; // If we have a buffer overflow error, try again with a larger buffer free(converted); converted = NULL; converted_len = converted_len * 2; } free(ustring); if (U_FAILURE(status)) { free(converted); return false; } // Convert the string back to UTF-8 status = U_ZERO_ERROR; intl_convert_utf16_to_utf8(&converted_utf8, &converted_utf8_len, converted, converted_ret_len, &status); free(converted); if (U_FAILURE(status)) { free(converted_utf8); return false; } // Return the string return String(converted_utf8, converted_utf8_len, AttachString); }
static void php_intl_idn_to(INTERNAL_FUNCTION_PARAMETERS, int mode) { unsigned char* domain; int domain_len; long option = 0; UChar* ustring = NULL; int ustring_len = 0; UErrorCode status; char *converted_utf8; int32_t converted_utf8_len; UChar converted[MAXPATHLEN]; int32_t converted_ret_len; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|l", (char **)&domain, &domain_len, &option) == FAILURE) { return; } if (domain_len < 1) { intl_error_set( NULL, U_ILLEGAL_ARGUMENT_ERROR, "idn_to_ascii: empty domain name", 0 TSRMLS_CC ); RETURN_FALSE; } /* convert the string to UTF-16. */ status = U_ZERO_ERROR; intl_convert_utf8_to_utf16(&ustring, &ustring_len, (char*) domain, domain_len, &status ); if (U_FAILURE(status)) { intl_error_set_code(NULL, status TSRMLS_CC); /* Set error messages. */ intl_error_set_custom_msg( NULL, "Error converting input string to UTF-16", 0 TSRMLS_CC ); efree(ustring); RETURN_FALSE; } else { UParseError parse_error; status = U_ZERO_ERROR; if (mode == INTL_IDN_TO_ASCII) { converted_ret_len = uidna_IDNToASCII(ustring, ustring_len, converted, MAXPATHLEN, (int32_t)option, &parse_error, &status); } else { converted_ret_len = uidna_IDNToUnicode(ustring, ustring_len, converted, MAXPATHLEN, (int32_t)option, &parse_error, &status); } efree(ustring); if (U_FAILURE(status)) { intl_error_set( NULL, status, "idn_to_ascii: cannot convert to ASCII", 0 TSRMLS_CC ); RETURN_FALSE; } status = U_ZERO_ERROR; intl_convert_utf16_to_utf8(&converted_utf8, &converted_utf8_len, converted, converted_ret_len, &status); if (U_FAILURE(status)) { /* Set global error code. */ intl_error_set_code(NULL, status TSRMLS_CC); /* Set error messages. */ intl_error_set_custom_msg( NULL, "Error converting output string to UTF-8", 0 TSRMLS_CC ); efree(converted_utf8); RETURN_FALSE; } } /* return the allocated string, not a duplicate */ RETURN_STRINGL(((char *)converted_utf8), converted_utf8_len, 0); }
static void php_intl_idn_to(INTERNAL_FUNCTION_PARAMETERS, const zend_string *domain, uint32_t option, int mode) { UChar* ustring = NULL; int ustring_len = 0; UErrorCode status; zend_string *u8str; /* convert the string to UTF-16. */ status = U_ZERO_ERROR; intl_convert_utf8_to_utf16(&ustring, &ustring_len, ZSTR_VAL(domain), ZSTR_LEN(domain), &status); if (U_FAILURE(status)) { intl_error_set_code(NULL, status); /* Set error messages. */ intl_error_set_custom_msg( NULL, "Error converting input string to UTF-16", 0 ); if (ustring) { efree(ustring); } RETURN_FALSE; } else { UChar converted[MAXPATHLEN]; int32_t converted_ret_len; status = U_ZERO_ERROR; #if U_ICU_VERSION_MAJOR_NUM >= 55 UIDNAInfo info = UIDNA_INFO_INITIALIZER; UIDNA *idna = uidna_openUTS46((int32_t)option, &status); if (U_FAILURE(status)) { intl_error_set( NULL, status, "idn_to_ascii: failed to create an UIDNA instance", 0 ); RETURN_FALSE; } if (mode == INTL_IDN_TO_ASCII) { converted_ret_len = uidna_nameToASCII(idna, ustring, ustring_len, converted, MAXPATHLEN, &info, &status); } else { converted_ret_len = uidna_nameToUnicode(idna, ustring, ustring_len, converted, MAXPATHLEN, &info, &status); } uidna_close(idna); #else UParseError parse_error; if (mode == INTL_IDN_TO_ASCII) { converted_ret_len = uidna_IDNToASCII(ustring, ustring_len, converted, MAXPATHLEN, (int32_t)option, &parse_error, &status); } else { converted_ret_len = uidna_IDNToUnicode(ustring, ustring_len, converted, MAXPATHLEN, (int32_t)option, &parse_error, &status); } #endif efree(ustring); if (U_FAILURE(status)) { intl_error_set( NULL, status, "idn_to_ascii: cannot convert to ASCII", 0 ); RETURN_FALSE; } status = U_ZERO_ERROR; u8str = intl_convert_utf16_to_utf8(converted, converted_ret_len, &status); if (!u8str) { /* Set global error code. */ intl_error_set_code(NULL, status); /* Set error messages. */ intl_error_set_custom_msg( NULL, "Error converting output string to UTF-8", 0 ); RETURN_FALSE; } } /* return the allocated string, not a duplicate */ RETVAL_NEW_STR(u8str); }