static void php_intl_idn_to_46(INTERNAL_FUNCTION_PARAMETERS, const zend_string *domain, uint32_t option, int mode, zval *idna_info) { UErrorCode status = U_ZERO_ERROR; UIDNA *uts46; int32_t len; zend_string *buffer; UIDNAInfo info = UIDNA_INFO_INITIALIZER; uts46 = uidna_openUTS46(option, &status); if (php_intl_idn_check_status(status, "failed to open UIDNA instance") == FAILURE) { RETURN_FALSE; } if (mode == INTL_IDN_TO_ASCII) { const int32_t buffer_capac = 255; buffer = zend_string_alloc(buffer_capac, 0); len = uidna_nameToASCII_UTF8(uts46, ZSTR_VAL(domain), ZSTR_LEN(domain), ZSTR_VAL(buffer), buffer_capac, &info, &status); if (len >= buffer_capac || php_intl_idn_check_status(status, "failed to convert name") == FAILURE) { uidna_close(uts46); zend_string_efree(buffer); RETURN_FALSE; } } else { const int32_t buffer_capac = 252*4; buffer = zend_string_alloc(buffer_capac, 0); len = uidna_nameToUnicodeUTF8(uts46, ZSTR_VAL(domain), ZSTR_LEN(domain), ZSTR_VAL(buffer), buffer_capac, &info, &status); if (len >= buffer_capac || php_intl_idn_check_status(status, "failed to convert name") == FAILURE) { uidna_close(uts46); zend_string_efree(buffer); RETURN_FALSE; } } ZSTR_VAL(buffer)[len] = '\0'; ZSTR_LEN(buffer) = len; if (info.errors == 0) { RETVAL_STR_COPY(buffer); } else { RETVAL_FALSE; } if (idna_info) { add_assoc_str_ex(idna_info, "result", sizeof("result")-1, zend_string_copy(buffer)); add_assoc_bool_ex(idna_info, "isTransitionalDifferent", sizeof("isTransitionalDifferent")-1, info.isTransitionalDifferent); add_assoc_long_ex(idna_info, "errors", sizeof("errors")-1, (zend_long)info.errors); } zend_string_release(buffer); uidna_close(uts46); }
/* Function: ToUnicode Used by System.Globalization.IdnMapping.GetUnicodeCore to convert an ASCII name to Unicode Return values: 0: internal error during conversion. >0: the length of the converted string (not including the null terminator). */ extern "C" int32_t GlobalizationNative_ToUnicode( int32_t flags, const UChar* lpSrc, int32_t cwSrcLength, UChar* lpDst, int32_t cwDstLength) { UErrorCode err = U_ZERO_ERROR; UIDNAInfo info = UIDNA_INFO_INITIALIZER; UIDNA* pIdna = uidna_openUTS46(GetOptions(flags), &err); int32_t unicodeStrLen = uidna_nameToUnicode(pIdna, lpSrc, cwSrcLength, lpDst, cwDstLength, &info, &err); uidna_close(pIdna); return ((U_SUCCESS(err) || (err == U_BUFFER_OVERFLOW_ERROR)) && (info.errors == 0)) ? unicodeStrLen : 0; }
static Variant php_intl_idn_to_46(const String& domain, int64_t options, IdnVariant idn_variant, VRefParam idna_info, int mode) { int32_t converted_capacity; char *converted = NULL; int32_t converted_len; UIDNA *uts46; UIDNAInfo info = UIDNA_INFO_INITIALIZER; UErrorCode status = U_ZERO_ERROR; // Get UIDNA instance which implements UTS #46. uts46 = uidna_openUTS46(options, &status); SCOPE_EXIT { uidna_close(uts46); }; if (U_FAILURE(status)) return false; // Call the appropriate IDN function status = U_ZERO_ERROR; converted_capacity = 255; // no domain name may exceed this String result(converted_capacity, ReserveString); // reserves converted_capacity+1 characters. converted = result.bufferSlice().ptr; if (mode == INTL_IDN_TO_ASCII) { converted_len = uidna_nameToASCII_UTF8(uts46, (char*)domain.data(), domain.size(), converted, converted_capacity, &info, &status); } else { converted_len = uidna_nameToUnicodeUTF8(uts46, (char*)domain.data(), domain.size(), converted, converted_capacity, &info, &status); } if (U_FAILURE(status) || converted_len > converted_capacity) return false; if (info.errors == 0) { result.setSize(converted_len); } else { result.setSize(0); } // Set up the array returned in idna_info. ArrayInit arr(3); arr.set(s_result, result); arr.set(s_isTransitionalDifferent, info.isTransitionalDifferent); arr.set(s_errors, (long)info.errors); // As in Zend, the previous value of idn_variant is overwritten, not modified. idna_info = arr.create(); if (info.errors == 0) { return result; } return false; }
static void php_intl_idn_to_46(INTERNAL_FUNCTION_PARAMETERS, const char *domain, int32_t domain_len, uint32_t option, int mode, zval *idna_info) { UErrorCode status = U_ZERO_ERROR; UIDNA *uts46; int32_t len; int32_t buffer_capac = 255; /* no domain name may exceed this */ zend_string *buffer = zend_string_alloc(buffer_capac, 0); UIDNAInfo info = UIDNA_INFO_INITIALIZER; int buffer_used = 0; uts46 = uidna_openUTS46(option, &status); if (php_intl_idn_check_status(status, "failed to open UIDNA instance", mode) == FAILURE) { zend_string_free(buffer); RETURN_FALSE; } if (mode == INTL_IDN_TO_ASCII) { len = uidna_nameToASCII_UTF8(uts46, domain, domain_len, ZSTR_VAL(buffer), buffer_capac, &info, &status); } else { len = uidna_nameToUnicodeUTF8(uts46, domain, domain_len, ZSTR_VAL(buffer), buffer_capac, &info, &status); } if (php_intl_idn_check_status(status, "failed to convert name", mode) == FAILURE) { uidna_close(uts46); zend_string_free(buffer); RETURN_FALSE; } if (len >= 255) { php_error_docref(NULL, E_ERROR, "ICU returned an unexpected length"); } ZSTR_VAL(buffer)[len] = '\0'; ZSTR_LEN(buffer) = len; if (info.errors == 0) { RETVAL_STR(buffer); buffer_used = 1; } else { RETVAL_FALSE; } if (idna_info) { if (buffer_used) { /* used in return_value then */ zval_addref_p(return_value); add_assoc_zval_ex(idna_info, "result", sizeof("result")-1, return_value); } else { zval zv; ZVAL_NEW_STR(&zv, buffer); buffer_used = 1; add_assoc_zval_ex(idna_info, "result", sizeof("result")-1, &zv); } add_assoc_bool_ex(idna_info, "isTransitionalDifferent", sizeof("isTransitionalDifferent")-1, info.isTransitionalDifferent); add_assoc_long_ex(idna_info, "errors", sizeof("errors")-1, (zend_long)info.errors); } if (!buffer_used) { zend_string_free(buffer); } uidna_close(uts46); }
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); }
/** * psl_load_fp: * @fp: FILE pointer * * This function loads the public suffixes from a FILE pointer. * To free the allocated resources, call psl_free(). * * The suffixes are expected to be lowercase UTF-8 encoded if they are international. * * Returns: Pointer to a PSL context or %NULL on failure. * * Since: 0.1 */ psl_ctx_t *psl_load_fp(FILE *fp) { psl_ctx_t *psl; _psl_entry_t suffix, *suffixp; char buf[256], *linep, *p; #ifdef WITH_LIBICU UIDNA *idna; UErrorCode status = 0; #endif if (!fp) return NULL; if (!(psl = calloc(1, sizeof(psl_ctx_t)))) return NULL; #ifdef WITH_LIBICU idna = uidna_openUTS46(UIDNA_USE_STD3_RULES, &status); #endif /* * as of 02.11.2012, the list at http://publicsuffix.org/list/ contains ~6000 rules and 40 exceptions. * as of 19.02.2014, the list at http://publicsuffix.org/list/ contains ~6500 rules and 19 exceptions. */ psl->suffixes = _vector_alloc(8*1024, _suffix_compare); psl->suffix_exceptions = _vector_alloc(64, _suffix_compare); while ((linep = fgets(buf, sizeof(buf), fp))) { while (isspace(*linep)) linep++; /* ignore leading whitespace */ if (!*linep) continue; /* skip empty lines */ if (*linep == '/' && linep[1] == '/') continue; /* skip comments */ /* parse suffix rule */ for (p = linep; *linep && !isspace(*linep);) linep++; *linep = 0; if (*p == '!') { /* add to exceptions */ if (_suffix_init(&suffix, p + 1, linep - p - 1) == 0) { suffixp = _vector_get(psl->suffix_exceptions, _vector_add(psl->suffix_exceptions, &suffix)); suffixp->label = suffixp->label_buf; /* set label to changed address */ #ifdef WITH_LIBICU _add_punycode_if_needed(idna, psl->suffix_exceptions, suffixp); #elif defined(WITH_LIBIDN2) || defined(WITH_LIBIDN) _add_punycode_if_needed(psl->suffix_exceptions, suffixp); #endif } } else { /* add to suffixes */ if (_suffix_init(&suffix, p, linep - p) == 0) { suffixp = _vector_get(psl->suffixes, _vector_add(psl->suffixes, &suffix)); suffixp->label = suffixp->label_buf; /* set label to changed address */ #ifdef WITH_LIBICU _add_punycode_if_needed(idna, psl->suffixes, suffixp); #elif defined(WITH_LIBIDN2) || defined(WITH_LIBIDN) _add_punycode_if_needed(psl->suffixes, suffixp); #endif } } } _vector_sort(psl->suffix_exceptions); _vector_sort(psl->suffixes); #ifdef WITH_LIBICU if (idna) uidna_close(idna); #endif return psl; }