int dns_label_apply_idna(const char *encoded, size_t encoded_size, char *decoded, size_t decoded_max) {
#ifdef HAVE_LIBIDN
        _cleanup_free_ uint32_t *input = NULL;
        size_t input_size;
        const char *p;
        bool contains_8bit = false;

        assert(encoded);
        assert(decoded);
        assert(decoded_max >= DNS_LABEL_MAX);

        if (encoded_size <= 0)
                return 0;

        for (p = encoded; p < encoded + encoded_size; p++)
                if ((uint8_t) *p > 127)
                        contains_8bit = true;

        if (!contains_8bit)
                return 0;

        input = stringprep_utf8_to_ucs4(encoded, encoded_size, &input_size);
        if (!input)
                return -ENOMEM;

        if (idna_to_ascii_4i(input, input_size, decoded, 0) != 0)
                return -EINVAL;

        return strlen(decoded);
#else
        return 0;
#endif
}
示例#2
0
文件: idna.c 项目: AubrCool/glibc
/**
 * idna_to_ascii_4z:
 * @input: zero terminated input Unicode string.
 * @output: pointer to newly allocated output string.
 * @flags: IDNA flags, e.g. IDNA_ALLOW_UNASSIGNED or IDNA_USE_STD3_ASCII_RULES.
 *
 * Convert UCS-4 domain name to ASCII string.  The domain name may
 * contain several labels, separated by dots.  The output buffer must
 * be deallocated by the caller.
 *
 * Return value: Returns IDNA_SUCCESS on success, or error code.
 **/
int
idna_to_ascii_4z (const uint32_t * input, char **output, int flags)
{
  const uint32_t *start = input;
  const uint32_t *end = input;
  char buf[64];
  char *out = NULL;
  int rc;

  /* 1) Whenever dots are used as label separators, the following
     characters MUST be recognized as dots: U+002E (full stop),
     U+3002 (ideographic full stop), U+FF0E (fullwidth full stop),
     U+FF61 (halfwidth ideographic full stop). */

  if (input[0] == 0)
    {
      /* Handle implicit zero-length root label. */
      *output = malloc (1);
      if (!*output)
	return IDNA_MALLOC_ERROR;
      strcpy (*output, "");
      return IDNA_SUCCESS;
    }

  if (DOTP (input[0]) && input[1] == 0)
    {
      /* Handle explicit zero-length root label. */
      *output = malloc (2);
      if (!*output)
	return IDNA_MALLOC_ERROR;
      strcpy (*output, ".");
      return IDNA_SUCCESS;
    }

  *output = NULL;
  do
    {
      end = start;

      for (; *end && !DOTP (*end); end++)
	;

      if (*end == '\0' && start == end)
	{
	  /* Handle explicit zero-length root label. */
	  buf[0] = '\0';
	}
      else
	{
	  rc = idna_to_ascii_4i (start, end - start, buf, flags);
	  if (rc != IDNA_SUCCESS)
	    return rc;
	}

      if (out)
	{
	  char *newp = realloc (out, strlen (out) + 1 + strlen (buf) + 1);
	  if (!newp)
	    {
	      free (out);
	      return IDNA_MALLOC_ERROR;
	    }
	  out = newp;
	  strcat (out, ".");
	  strcat (out, buf);
	}
      else
	{
	  out = (char *) malloc (strlen (buf) + 1);
	  if (!out)
	    return IDNA_MALLOC_ERROR;
	  strcpy (out, buf);
	}

      start = end + 1;
    }
  while (*end);

  *output = out;

  return IDNA_SUCCESS;
}
示例#3
0
文件: idna.c 项目: AubrCool/glibc
/* ToUnicode().  May realloc() utf8in. */
static int
idna_to_unicode_internal (char *utf8in,
			  uint32_t * out, size_t * outlen, int flags)
{
  int rc;
  char tmpout[64];
  size_t utf8len = strlen (utf8in) + 1;
  size_t addlen = 0;

  /*
   * ToUnicode consists of the following steps:
   *
   * 1. If the sequence contains any code points outside the ASCII range
   * (0..7F) then proceed to step 2, otherwise skip to step 3.
   */

  {
    size_t i;
    int inasciirange;

    inasciirange = 1;
    for (i = 0; utf8in[i]; i++)
      if (utf8in[i] & ~0x7F)
	inasciirange = 0;
    if (inasciirange)
      goto step3;
  }

  /*
   * 2. Perform the steps specified in [NAMEPREP] and fail if there is an
   * error. (If step 3 of ToASCII is also performed here, it will not
   * affect the overall behavior of ToUnicode, but it is not
   * necessary.) The AllowUnassigned flag is used in [NAMEPREP].
   */
  do
    {
      char *newp = realloc (utf8in, utf8len + addlen);
      if (newp == NULL)
	{
	  free (utf8in);
	  return IDNA_MALLOC_ERROR;
	}
      utf8in = newp;
      if (flags & IDNA_ALLOW_UNASSIGNED)
	rc = stringprep_nameprep (utf8in, utf8len + addlen);
      else
	rc = stringprep_nameprep_no_unassigned (utf8in, utf8len + addlen);
      addlen += 1;
    }
  while (rc == STRINGPREP_TOO_SMALL_BUFFER);

  if (rc != STRINGPREP_OK)
    {
      free (utf8in);
      return IDNA_STRINGPREP_ERROR;
    }

  /* 3. Verify that the sequence begins with the ACE prefix, and save a
   * copy of the sequence.
   */

step3:
  if (memcmp (IDNA_ACE_PREFIX, utf8in, strlen (IDNA_ACE_PREFIX)) != 0)
    {
      free (utf8in);
      return IDNA_NO_ACE_PREFIX;
    }

  /* 4. Remove the ACE prefix.
   */

  memmove (utf8in, &utf8in[strlen (IDNA_ACE_PREFIX)],
	   strlen (utf8in) - strlen (IDNA_ACE_PREFIX) + 1);

  /* 5. Decode the sequence using the decoding algorithm in [PUNYCODE]
   * and fail if there is an error. Save a copy of the result of
   * this step.
   */

  (*outlen)--;			/* reserve one for the zero */

  rc = punycode_decode (strlen (utf8in), utf8in, outlen, out, NULL);
  if (rc != PUNYCODE_SUCCESS)
    {
      free (utf8in);
      return IDNA_PUNYCODE_ERROR;
    }

  out[*outlen] = 0;		/* add zero */

  /* 6. Apply ToASCII.
   */

  rc = idna_to_ascii_4i (out, *outlen, tmpout, flags);
  if (rc != IDNA_SUCCESS)
    {
      free (utf8in);
      return rc;
    }

  /* 7. Verify that the result of step 6 matches the saved copy from
   * step 3, using a case-insensitive ASCII comparison.
   */

  if (strcasecmp (utf8in, tmpout + strlen (IDNA_ACE_PREFIX)) != 0)
    {
      free (utf8in);
      return IDNA_ROUNDTRIP_VERIFY_ERROR;
    }

  /* 8. Return the saved copy from step 5.
   */

  free (utf8in);
  return IDNA_SUCCESS;
}
示例#4
0
void
doit (void)
{
  char label[100];
  uint32_t *ucs4label = NULL;
  uint32_t tmp[100];
  size_t len, len2, i;
  int rc;

  for (i = 0; i < sizeof (idna) / sizeof (idna[0]); i++)
    {
      if (debug)
	printf ("IDNA entry %d: %s\n", i, idna[i].name);

      if (debug)
	{
	  printf ("in:\n");
	  ucs4print (idna[i].in, idna[i].inlen);
	}

      rc = idna_to_ascii_4i (idna[i].in, idna[i].inlen, label, idna[i].flags);
      if (rc != idna[i].toasciirc)
	{
	  fail ("IDNA entry %d failed: %d\n", i, rc);
	  if (debug)
	    printf ("FATAL\n");
	  continue;
	}

      if (debug && rc == IDNA_SUCCESS)
	{
	  printf ("computed out: %s\n", label);
	  printf ("expected out: %s\n", idna[i].out);
	}
      else if (debug)
	printf ("returned %d expected %d\n", rc, idna[i].toasciirc);

      if (rc == IDNA_SUCCESS)
	{
	  if (strlen (idna[i].out) != strlen (label) ||
	      strcasecmp (idna[i].out, label) != 0)
	    {
	      fail ("IDNA entry %d failed\n", i);
	      if (debug)
		printf ("ERROR\n");
	    }
	  else if (debug)
	    printf ("OK\n");
	}
      else if (debug)
	printf ("OK\n");

      if (ucs4label)
	free (ucs4label);

      ucs4label = stringprep_utf8_to_ucs4 (idna[i].out, -1, &len);

      if (debug)
	{
	  printf ("in: %s (%d==%d)\n", idna[i].out, strlen (idna[i].out),
		  len);
	  ucs4print (ucs4label, len);
	}

      len2 = sizeof (tmp) / sizeof (tmp[0]);
      rc = idna_to_unicode_44i (ucs4label, len, tmp, &len2, idna[i].flags);
      if (debug)
	{
	  printf ("expected out (%d):\n",
		  rc == IDNA_SUCCESS ? idna[i].inlen : len);
	  if (rc == IDNA_SUCCESS)
	    ucs4print (idna[i].in, idna[i].inlen);
	  else
	    ucs4print (ucs4label, len);

	  printf ("computed out (%d):\n", len2);
	  ucs4print (tmp, len2);
	}

      if (rc != idna[i].tounicoderc)
	{
	  fail ("IDNA entry %d failed: %d\n", i, rc);
	  if (debug)
	    printf ("FATAL\n");
	  continue;
	}

      if ((rc == IDNA_SUCCESS && (len2 != idna[i].inlen ||
				  memcmp (idna[i].in, tmp, len2) != 0)) ||
	  (rc != IDNA_SUCCESS && (len2 != len ||
				  memcmp (ucs4label, tmp, len) != 0)))
	{
	  if (debug)
	    {
	      if (rc == IDNA_SUCCESS)
		printf ("len=%d len2=%d\n", len2, idna[i].inlen);
	      else
		printf ("len=%d len2=%d\n", len, len2);
	    }
	  fail ("IDNA entry %d failed\n", i);
	  if (debug)
	    printf ("ERROR\n");
	}
      else if (debug)
	printf ("OK\n\n");
    }

  if (ucs4label)
    free (ucs4label);
}