Beispiel #1
0
static void php_intl_idn_handoff(INTERNAL_FUNCTION_PARAMETERS, int mode)
{
	zend_string *domain;
	zend_long option = 0,
	variant = INTL_IDN_VARIANT_UTS46;
	zval *idna_info = NULL;

	intl_error_reset(NULL);

	if (zend_parse_parameters(ZEND_NUM_ARGS(), "S|llz",
			&domain, &option, &variant, &idna_info) == FAILURE) {
		RETURN_NULL(); /* don't set FALSE because that's not the way it was before... */
	}

	if (variant != INTL_IDN_VARIANT_UTS46) {
		php_intl_bad_args("invalid variant, must be INTL_IDNA_VARIANT_UTS46");
		RETURN_FALSE;
	}

	if (ZSTR_LEN(domain) < 1) {
		php_intl_bad_args("empty domain name");
		RETURN_FALSE;
	}
	if (ZSTR_LEN(domain) > INT32_MAX - 1) {
		php_intl_bad_args("domain name too large");
		RETURN_FALSE;
	}
	/* don't check options; it wasn't checked before */

	if (idna_info != NULL) {
		idna_info = zend_try_array_init(idna_info);
		if (!idna_info) {
			return;
		}
	}

	php_intl_idn_to_46(INTERNAL_FUNCTION_PARAM_PASSTHRU, domain, (uint32_t)option, mode, idna_info);
}
Beispiel #2
0
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);
}
Beispiel #3
0
static void php_intl_idn_handoff(INTERNAL_FUNCTION_PARAMETERS, int mode)
{
	char *domain;
	size_t domain_len;
	zend_long option = 0,
		 variant = INTL_IDN_VARIANT_2003;
	zval *idna_info = NULL;

	intl_error_reset(NULL);

	if (zend_parse_parameters(ZEND_NUM_ARGS(), "s|llz/",
			&domain, &domain_len, &option, &variant, &idna_info) == FAILURE) {
		php_intl_bad_args("bad arguments", mode);
		RETURN_NULL(); /* don't set FALSE because that's not the way it was before... */
	}

#ifdef HAVE_46_API
	if (variant != INTL_IDN_VARIANT_2003 && variant != INTL_IDN_VARIANT_UTS46) {
		php_intl_bad_args("invalid variant, must be one of {"
			"INTL_IDNA_VARIANT_2003, INTL_IDNA_VARIANT_UTS46}", mode);
		RETURN_FALSE;
	}
#else
	if (variant != INTL_IDN_VARIANT_2003) {
		php_intl_bad_args("invalid variant, PHP was compiled against "
			"an old version of ICU and only supports INTL_IDN_VARIANT_2003",
			mode);
		RETURN_FALSE;
	}
#endif

	if (domain_len < 1) {
		php_intl_bad_args("empty domain name", mode);
		RETURN_FALSE;
	}
	if (domain_len > INT32_MAX - 1) {
		php_intl_bad_args("domain name too large", mode);
		RETURN_FALSE;
	}
	/* don't check options; it wasn't checked before */

	if (idna_info != NULL) {
		if (variant == INTL_IDN_VARIANT_2003) {
			php_error_docref0(NULL, E_NOTICE,
				"4 arguments were provided, but INTL_IDNA_VARIANT_2003 only "
				"takes 3 - extra argument ignored");
		} else {
			zval_dtor(idna_info);
			array_init(idna_info);
		}
	}

	if (variant == INTL_IDN_VARIANT_2003) {
		php_intl_idn_to(INTERNAL_FUNCTION_PARAM_PASSTHRU,
				domain, (int32_t)domain_len, (uint32_t)option, mode);
	}
#ifdef HAVE_46_API
	else {
		php_intl_idn_to_46(INTERNAL_FUNCTION_PARAM_PASSTHRU, domain, (int32_t)domain_len,
				(uint32_t)option, mode, idna_info);
	}
#endif
}