示例#1
0
文件: utf8.c 项目: Exim/exim
uschar *
string_localpart_utf8_to_alabel(const uschar * utf8, uschar ** err)
{
size_t ucs4_len;
punycode_uint * p;
size_t p_len;
uschar * res;
int rc;

if (!string_is_utf8(utf8)) return string_copy(utf8);

p = (punycode_uint *) stringprep_utf8_to_ucs4(CCS utf8, -1, &ucs4_len);
p_len = ucs4_len*4;	/* this multiplier is pure guesswork */
res = store_get(p_len+5);

res[0] = 'x'; res[1] = 'n'; res[2] = res[3] = '-';

if ((rc = punycode_encode(ucs4_len, p, NULL, &p_len, CS res+4)) != PUNYCODE_SUCCESS)
  {
  DEBUG(D_expand) debug_printf("l_u2a: bad '%s'\n", punycode_strerror(rc));
  free(p);
  if (err) *err = US punycode_strerror(rc);
  return NULL;
  }
p_len += 4;
free(p);
res[p_len] = '\0';
return res;
}
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
}
示例#3
0
文件: tst_nfkc.c 项目: guusdk/libidn
void
doit (void)
{
  char *out;
  size_t i;

  for (i = 0; i < sizeof (nfkc) / sizeof (nfkc[0]); i++)
    {
      if (debug)
	printf ("NFKC entry %ld\n", i);

      out = stringprep_utf8_nfkc_normalize (nfkc[i].in,
					    (ssize_t) strlen (nfkc[i].in));
      if (out == NULL)
	{
	  fail ("NFKC entry %ld failed fatally\n", i);
	  continue;
	}

      if (debug)
	{
	  uint32_t *t;
	  size_t len;

	  printf ("in:\n");
	  escapeprint (nfkc[i].in, strlen (nfkc[i].in));
	  hexprint (nfkc[i].in, strlen (nfkc[i].in));
	  binprint (nfkc[i].in, strlen (nfkc[i].in));


	  printf ("out:\n");
	  escapeprint (out, strlen (out));
	  hexprint (out, strlen (out));
	  binprint (out, strlen (out));
	  t = stringprep_utf8_to_ucs4 (out, -1, &len);
	  if (t)
	    {
	      ucs4print (t, len);
	      free (t);
	    }

	  printf ("expected out:\n");
	  escapeprint (nfkc[i].out, strlen (nfkc[i].out));
	  hexprint (nfkc[i].out, strlen (nfkc[i].out));
	  binprint (nfkc[i].out, strlen (nfkc[i].out));
	}

      if (strlen (nfkc[i].out) != strlen (out) ||
	  memcmp (nfkc[i].out, out, strlen (out)) != 0)
	{
	  fail ("NFKC entry %ld failed\n", i);
	  if (debug)
	    printf ("ERROR\n");
	}
      else if (debug)
	printf ("OK\n");

      free (out);
    }
}
示例#4
0
/**
 * stringprep - prepare internationalized string
 * @in: input/ouput array with string to prepare.
 * @maxlen: maximum length of input/output array.
 * @flags: a #Stringprep_profile_flags value, or 0.
 * @profile: pointer to #Stringprep_profile to use.
 *
 * Prepare the input zero terminated UTF-8 string according to the
 * stringprep profile, and write back the result to the input string.
 *
 * Note that you must convert strings entered in the systems locale
 * into UTF-8 before using this function, see
 * stringprep_locale_to_utf8().
 *
 * Since the stringprep operation can expand the string, @maxlen
 * indicate how large the buffer holding the string is.  This function
 * will not read or write to characters outside that size.
 *
 * The @flags are one of #Stringprep_profile_flags values, or 0.
 *
 * The @profile contain the #Stringprep_profile instructions to
 * perform.  Your application can define new profiles, possibly
 * re-using the generic stringprep tables that always will be part of
 * the library, or use one of the currently supported profiles.
 *
 * Return value: Returns %STRINGPREP_OK iff successful, or an error code.
 **/
int
stringprep (char *in,
	    size_t maxlen,
	    Stringprep_profile_flags flags,
	    const Stringprep_profile * profile)
{
  int rc;
  char *utf8 = NULL;
  uint32_t *ucs4 = NULL;
  size_t ucs4len, maxucs4len, adducs4len = 50;

  do
    {
      uint32_t *newp;

      if (ucs4)
	free (ucs4);
      ucs4 = stringprep_utf8_to_ucs4 (in, -1, &ucs4len);
      maxucs4len = ucs4len + adducs4len;
      newp = realloc (ucs4, maxucs4len * sizeof (uint32_t));
      if (!newp)
	{
	  free (ucs4);
	  return STRINGPREP_MALLOC_ERROR;
	}
      ucs4 = newp;

      rc = stringprep_4i (ucs4, &ucs4len, maxucs4len, flags, profile);
      adducs4len += 50;
    }
  while (rc == STRINGPREP_TOO_SMALL_BUFFER);
  if (rc != STRINGPREP_OK)
    {
      free (ucs4);
      return rc;
    }

  utf8 = stringprep_ucs4_to_utf8 (ucs4, ucs4len, 0, 0);
  free (ucs4);
  if (!utf8)
    return STRINGPREP_MALLOC_ERROR;

  if (strlen (utf8) >= maxlen)
    {
      free (utf8);
      return STRINGPREP_TOO_SMALL_BUFFER;
    }

  strcpy (in, utf8);		/* flawfinder: ignore */

  free (utf8);

  return STRINGPREP_OK;
}
示例#5
0
文件: idna.c 项目: AubrCool/glibc
/**
 * idna_to_unicode_8z4z:
 * @input: zero-terminated UTF-8 string.
 * @output: pointer to newly allocated output Unicode string.
 * @flags: IDNA flags, e.g. IDNA_ALLOW_UNASSIGNED or IDNA_USE_STD3_ASCII_RULES.
 *
 * Convert possibly ACE encoded domain name in UTF-8 format into a
 * UCS-4 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_unicode_8z4z (const char *input, uint32_t ** output, int flags)
{
  uint32_t *ucs4;
  size_t ucs4len;
  int rc;

  ucs4 = stringprep_utf8_to_ucs4 (input, -1, &ucs4len);
  if (!ucs4)
    return IDNA_ICONV_ERROR;

  rc = idna_to_unicode_4z4z (ucs4, output, flags);
  free (ucs4);

  return rc;
}
int dns_label_undo_idna(const char *encoded, size_t encoded_size, char *decoded, size_t decoded_max) {
#ifdef HAVE_LIBIDN
        size_t input_size, output_size;
        _cleanup_free_ uint32_t *input = NULL;
        _cleanup_free_ char *result = NULL;
        uint32_t *output = NULL;
        size_t w;

        /* To be invoked after unescaping */

        assert(encoded);
        assert(decoded);

        if (encoded_size < sizeof(IDNA_ACE_PREFIX)-1)
                return 0;

        if (memcmp(encoded, IDNA_ACE_PREFIX, sizeof(IDNA_ACE_PREFIX) -1) != 0)
                return 0;

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

        output_size = input_size;
        output = newa(uint32_t, output_size);

        idna_to_unicode_44i(input, input_size, output, &output_size, 0);

        result = stringprep_ucs4_to_utf8(output, output_size, NULL, &w);
        if (!result)
                return -ENOMEM;
        if (w <= 0)
                return 0;
        if (w+1 > decoded_max)
                return -EINVAL;

        memcpy(decoded, result, w+1);
        return w;
#else
        return 0;
#endif
}
示例#7
0
static VALUE encode(VALUE self, VALUE str)
{
  int rc;
  punycode_uint *ustr;
  size_t len;
  size_t buflen = 0x100;
  char *buf = NULL;
  VALUE retv;

  str = rb_check_convert_type(str, T_STRING, "String", "to_s");
  ustr = stringprep_utf8_to_ucs4(RSTRING_PTR(str), RSTRING_LEN(str), &len);

  while (1) {
    buf = realloc(buf, buflen);

    if (buf == NULL) {
      xfree(ustr);
      rb_raise(rb_eNoMemError, "cannot allocate memory (%d bytes)", (uint32_t)buflen);
      return Qnil;
    }

    rc = punycode_encode(len, ustr, NULL, &buflen, buf);

    if (rc == PUNYCODE_SUCCESS) {
      break;
    } else if (rc == PUNYCODE_BIG_OUTPUT) {
      buflen += 0x100;
    } else {
      xfree(ustr);
      xfree(buf);
      rb_raise(ePunycodeError, "%s (%d)", punycode_strerror(rc), rc);
      return Qnil;
    }
  }

  retv = rb_str_new(buf, buflen);
  xfree(ustr);
  xfree(buf);
  return retv;
}
示例#8
0
文件: idna.c 项目: AubrCool/glibc
/**
 * idna_to_ascii_4i
 * @in: input array with unicode code points.
 * @inlen: length of input array with unicode code points.
 * @out: output zero terminated string that must have room for at
 *       least 63 characters plus the terminating zero.
 * @flags: IDNA flags, e.g. IDNA_ALLOW_UNASSIGNED or IDNA_USE_STD3_ASCII_RULES.
 *
 * The ToASCII operation takes a sequence of Unicode code points that make
 * up one label and transforms it into a sequence of code points in the
 * ASCII range (0..7F). If ToASCII succeeds, the original sequence and the
 * resulting sequence are equivalent labels.
 *
 * It is important to note that the ToASCII operation can fail. ToASCII
 * fails if any step of it fails. If any step of the ToASCII operation
 * fails on any label in a domain name, that domain name MUST NOT be used
 * as an internationalized domain name. The method for deadling with this
 * failure is application-specific.
 *
 * The inputs to ToASCII are a sequence of code points, the AllowUnassigned
 * flag, and the UseSTD3ASCIIRules flag. The output of ToASCII is either a
 * sequence of ASCII code points or a failure condition.
 *
 * ToASCII never alters a sequence of code points that are all in the ASCII
 * range to begin with (although it could fail). Applying the ToASCII
 * operation multiple times has exactly the same effect as applying it just
 * once.
 *
 * Return value: Returns 0 on success, or an error code.
 */
int
idna_to_ascii_4i (const uint32_t * in, size_t inlen, char *out, int flags)
{
  size_t len, outlen;
  uint32_t *src;		/* XXX don't need to copy data? */
  int rc;

  /*
   * ToASCII consists of the following steps:
   *
   * 1. If all code points in the sequence are in the ASCII range (0..7F)
   * then skip to step 3.
   */

  {
    size_t i;
    int inasciirange;

    inasciirange = 1;
    for (i = 0; i < inlen; i++)
      if (in[i] > 0x7F)
	inasciirange = 0;
    if (inasciirange)
      {
	src = malloc (sizeof (in[0]) * (inlen + 1));
	if (src == NULL)
	  return IDNA_MALLOC_ERROR;

	memcpy (src, in, sizeof (in[0]) * inlen);
	src[inlen] = 0;

	goto step3;
      }
  }

  /*
   * 2. Perform the steps specified in [NAMEPREP] and fail if there is
   * an error. The AllowUnassigned flag is used in [NAMEPREP].
   */

  {
    char *p;

    p = stringprep_ucs4_to_utf8 (in, inlen, NULL, NULL);
    if (p == NULL)
      return IDNA_MALLOC_ERROR;

    len = strlen (p);
    do
      {
	char *newp;

	len = 2 * len + 10;	/* XXX better guess? */
	newp = realloc (p, len);
	if (newp == NULL)
	  {
	    free (p);
	    return IDNA_MALLOC_ERROR;
	  }
	p = newp;

	if (flags & IDNA_ALLOW_UNASSIGNED)
	  rc = stringprep_nameprep (p, len);
	else
	  rc = stringprep_nameprep_no_unassigned (p, len);
      }
    while (rc == STRINGPREP_TOO_SMALL_BUFFER);

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

    src = stringprep_utf8_to_ucs4 (p, -1, NULL);

    free (p);
  }

step3:
  /*
   * 3. If the UseSTD3ASCIIRules flag is set, then perform these checks:
   *
   * (a) Verify the absence of non-LDH ASCII code points; that is,
   * the absence of 0..2C, 2E..2F, 3A..40, 5B..60, and 7B..7F.
   *
   * (b) Verify the absence of leading and trailing hyphen-minus;
   * that is, the absence of U+002D at the beginning and end of
   * the sequence.
   */

  if (flags & IDNA_USE_STD3_ASCII_RULES)
    {
      size_t i;

      for (i = 0; src[i]; i++)
	if (src[i] <= 0x2C || src[i] == 0x2E || src[i] == 0x2F ||
	    (src[i] >= 0x3A && src[i] <= 0x40) ||
	    (src[i] >= 0x5B && src[i] <= 0x60) ||
	    (src[i] >= 0x7B && src[i] <= 0x7F))
	  {
	    free (src);
	    return IDNA_CONTAINS_NON_LDH;
	  }

      if (src[0] == 0x002D || (i > 0 && src[i - 1] == 0x002D))
	{
	  free (src);
	  return IDNA_CONTAINS_MINUS;
	}
    }

  /*
   * 4. If all code points in the sequence are in the ASCII range
   * (0..7F), then skip to step 8.
   */

  {
    size_t i;
    int inasciirange;

    inasciirange = 1;
    for (i = 0; src[i]; i++)
      {
	if (src[i] > 0x7F)
	  inasciirange = 0;
	/* copy string to output buffer if we are about to skip to step8 */
	if (i < 64)
	  out[i] = src[i];
      }
    if (i < 64)
      out[i] = '\0';
    if (inasciirange)
      goto step8;
  }

  /*
   * 5. Verify that the sequence does NOT begin with the ACE prefix.
   *
   */

  {
    size_t i;
    int match;

    match = 1;
    for (i = 0; match && i < strlen (IDNA_ACE_PREFIX); i++)
      if (((uint32_t) IDNA_ACE_PREFIX[i] & 0xFF) != src[i])
	match = 0;
    if (match)
      {
	free (src);
	return IDNA_CONTAINS_ACE_PREFIX;
      }
  }

  /*
   * 6. Encode the sequence using the encoding algorithm in [PUNYCODE]
   * and fail if there is an error.
   */
  for (len = 0; src[len]; len++)
    ;
  src[len] = '\0';
  outlen = 63 - strlen (IDNA_ACE_PREFIX);
  rc = punycode_encode (len, src, NULL,
			&outlen, &out[strlen (IDNA_ACE_PREFIX)]);
  if (rc != PUNYCODE_SUCCESS)
    {
      free (src);
      return IDNA_PUNYCODE_ERROR;
    }
  out[strlen (IDNA_ACE_PREFIX) + outlen] = '\0';

  /*
   * 7. Prepend the ACE prefix.
   */

  memcpy (out, IDNA_ACE_PREFIX, strlen (IDNA_ACE_PREFIX));

  /*
   * 8. Verify that the number of code points is in the range 1 to 63
   * inclusive (0 is excluded).
   */

step8:
  free (src);
  if (strlen (out) < 1 || strlen (out) > 63)
    return IDNA_INVALID_LENGTH;

  return IDNA_SUCCESS;
}
示例#9
0
void
doit (void)
{
  char *p;
  int rc;
  size_t i;

  if (!stringprep_check_version (STRINGPREP_VERSION))
    fail ("stringprep_check_version() failed\n");

  for (i = 0; i < sizeof (strprep) / sizeof (strprep[0]); i++)
    {
      if (debug)
	printf ("STRINGPREP entry %d\n", i);

      if (debug)
	{
	  printf ("flags: %d\n", strprep[i].flags);

	  printf ("in: ");
	  escapeprint (strprep[i].in, strlen (strprep[i].in));
	  hexprint (strprep[i].in, strlen (strprep[i].in));
	  binprint (strprep[i].in, strlen (strprep[i].in));
	}

      {
	uint32_t *l;
	char *x;
	l = stringprep_utf8_to_ucs4 (strprep[i].in, -1, NULL);
	x = stringprep_ucs4_to_utf8 (l, -1, NULL, NULL);
	free (l);

	if (strcmp (strprep[i].in, x) != 0)
	  {
	    fail ("bad UTF-8 in entry %d\n", i);
	    if (debug)
	      {
		puts ("expected:");
		escapeprint (strprep[i].in, strlen (strprep[i].in));
		hexprint (strprep[i].in, strlen (strprep[i].in));
		puts ("computed:");
		escapeprint (x, strlen (x));
		hexprint (x, strlen (x));
	      }
	  }

	free (x);
      }
      rc = stringprep_profile (strprep[i].in, &p,
			       strprep[i].profile ?
			       strprep[i].profile :
			       "Nameprep", strprep[i].flags);
      if (rc != strprep[i].rc)
	{
	  fail ("stringprep() entry %d failed: %d\n", i, rc);
	  if (debug)
	    printf ("FATAL\n");
	  if (rc == STRINGPREP_OK)
	    free (p);
	  continue;
	}

      if (debug && rc == STRINGPREP_OK)
	{
	  printf ("out: ");
	  escapeprint (p, strlen (p));
	  hexprint (p, strlen (p));
	  binprint (p, strlen (p));

	  printf ("expected out: ");
	  escapeprint (strprep[i].out, strlen (strprep[i].out));
	  hexprint (strprep[i].out, strlen (strprep[i].out));
	  binprint (strprep[i].out, strlen (strprep[i].out));
	}
      else if (debug)
	printf ("returned %d expected %d\n", rc, strprep[i].rc);

      if (rc == STRINGPREP_OK)
	{
	  if (strlen (strprep[i].out) != strlen (p) ||
	      memcmp (strprep[i].out, p, strlen (p)) != 0)
	    {
	      fail ("stringprep() entry %d failed\n", i);
	      if (debug)
		printf ("ERROR\n");
	    }
	  else if (debug)
	    printf ("OK\n\n");

	  free (p);
	}
      else if (debug)
	printf ("OK\n\n");
    }

#if 0
  {
    char p[20];
    memset (p, 0, 10);
    stringprep_unichar_to_utf8 (0x00DF, p);
    hexprint (p, strlen (p));
    puts ("");
  }
#endif
}
示例#10
0
文件: tst_idna2.c 项目: guusdk/libidn
void
doit (void)
{
  size_t i;
  char *out;
  int rc;

  for (i = 0; i < sizeof (idna) / sizeof (idna[0]); i++)
    {
      if (debug)
	printf ("IDNA2 entry %ld\n", i);

      if (debug)
	{
	  uint32_t *p;
	  size_t len;
	  printf ("in: %s\n", idna[i].in);
	  hexprint (idna[i].in, strlen (idna[i].in));
	  escapeprint (idna[i].in, strlen (idna[i].in));
	  p = stringprep_utf8_to_ucs4 (idna[i].in, -1, &len);
	  ucs4print (p, len);
	  free (p);
	}

      rc = idna_to_ascii_8z (idna[i].in, &out,
			     IDNA_ALLOW_UNASSIGNED |
			     IDNA_USE_STD3_ASCII_RULES);
      if (rc != IDNA_SUCCESS && strlen (idna[i].out) > 0)
	{
	  fail ("IDNA2 entry %ld failed: %d\n", i, rc);
	  continue;
	}

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

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

	  free (out);
	  out = NULL;
	}
      else if (rc != IDNA_SUCCESS && strlen (idna[i].out) == 0 && debug)
	printf ("OK (fail)\n");
      else if (debug)
	printf ("OK\n");
    }
}
示例#11
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);
}
示例#12
0
文件: idn.c 项目: bdw0920/uClinux
int
main (int argc, char *argv[])
{
  struct gengetopt_args_info args_info;
  char readbuf[BUFSIZ];
  char *p, *r;
  uint32_t *q;
  unsigned cmdn = 0;
  int rc;

  setlocale (LC_ALL, "");
  bindtextdomain (PACKAGE, LOCALEDIR);
  textdomain (PACKAGE);

  if (cmdline_parser (argc, argv, &args_info) != 0)
    return 1;

  if (!args_info.stringprep_given &&
      !args_info.punycode_encode_given && !args_info.punycode_decode_given &&
      !args_info.idna_to_ascii_given && !args_info.idna_to_unicode_given)
    args_info.idna_to_ascii_given = 1;

  if ((args_info.stringprep_given ? 1 : 0) +
      (args_info.punycode_encode_given ? 1 : 0) +
      (args_info.punycode_decode_given ? 1 : 0) +
      (args_info.idna_to_ascii_given ? 1 : 0) +
      (args_info.idna_to_unicode_given ? 1 : 0) != 1)
    {
      fprintf (stderr,
	       _("%s: Only one of -s, -e, -d, -a or -u can be specified.\n"),
	       argv[0]);
      cmdline_parser_print_help ();
      return 1;
    }

  if (!args_info.quiet_given)
    fprintf (stderr, "%s %s\n" GREETING, PACKAGE, VERSION);

  if (args_info.debug_given)
    fprintf (stderr, _("Charset `%s'.\n"), stringprep_locale_charset ());

  if (!args_info.quiet_given && args_info.inputs_num == 0)
    fprintf (stderr, _("Type each input string on a line by itself, "
		       "terminated by a newline character.\n"));

  do
    {
      if (cmdn < args_info.inputs_num)
	{
	  strncpy (readbuf, args_info.inputs[cmdn++], BUFSIZ - 1);
	  readbuf[BUFSIZ - 1] = '\0';
	}
      else if (fgets (readbuf, BUFSIZ, stdin) == NULL)
	{
	  sprintf (readbuf, _("%s: fgets() failed: "), argv[0]);
	  if (!feof (stdin))
	    perror (readbuf);
	  return 1;
	}

      if (readbuf[strlen (readbuf) - 1] == '\n')
	readbuf[strlen (readbuf) - 1] = '\0';

      if (args_info.stringprep_given)
	{
	  p = stringprep_locale_to_utf8 (readbuf);
	  if (!p)
	    {
	      fprintf (stderr, _("%s: could not convert from %s to UTF-8.\n"),
		       argv[0], stringprep_locale_charset ());
	      return 1;
	    }

	  q = stringprep_utf8_to_ucs4 (p, -1, NULL);
	  if (!q)
	    {
	      free (p);
	      fprintf (stderr,
		       _("%s: could not convert from UTF-8 to UCS-4.\n"),
		       argv[0]);
	      return 1;
	    }

	  if (args_info.debug_given)
	    {
	      size_t i;
	      for (i = 0; q[i]; i++)
		fprintf (stderr, _("input[%d] = U+%04x\n"), i, q[i]);
	    }
	  free (q);

	  rc = stringprep_profile (p, &r,
				   args_info.profile_given ?
				   args_info.profile_arg : "Nameprep", 0);
	  free (p);
	  if (rc != STRINGPREP_OK)
	    {
	      fprintf (stderr,
		       _("%s: stringprep_profile() failed with error %d.\n"),
		       argv[0], rc);
	      return 1;
	    }

	  q = stringprep_utf8_to_ucs4 (r, -1, NULL);
	  if (!q)
	    {
	      free (r);
	      fprintf (stderr,
		       _("%s: could not convert from UTF-8 to UCS-4.\n"),
		       argv[0]);
	      return 1;
	    }

	  if (args_info.debug_given)
	    {
	      size_t i;
	      for (i = 0; q[i]; i++)
		fprintf (stderr, _("output[%d] = U+%04x\n"), i, q[i]);
	    }
	  free (q);

	  p = stringprep_utf8_to_locale (r);
	  free (r);
	  if (!p)
	    {
	      fprintf (stderr, _("%s: could not convert from UTF-8 to %s.\n"),
		       argv[0], stringprep_locale_charset ());
	      return 1;
	    }

	  fprintf (stdout, "%s\n", p);

	  free (p);
	}

      if (args_info.punycode_encode_given)
	{
	  size_t len, len2;

	  p = stringprep_locale_to_utf8 (readbuf);
	  if (!p)
	    {
	      fprintf (stderr, _("%s: could not convert from %s to UTF-8.\n"),
		       argv[0], stringprep_locale_charset ());
	      return 1;
	    }

	  q = stringprep_utf8_to_ucs4 (p, -1, &len);
	  free (p);
	  if (!q)
	    {
	      fprintf (stderr,
		       _("%s: could not convert from UTF-8 to UCS-4.\n"),
		       argv[0]);
	      return 1;
	    }

	  if (args_info.debug_given)
	    {
	      size_t i;
	      for (i = 0; i < len; i++)
		fprintf (stderr, _("input[%d] = U+%04x\n"), i, q[i]);
	    }

	  len2 = BUFSIZ;
	  rc = punycode_encode (len, q, NULL, &len2, readbuf);
	  free (q);
	  if (rc != PUNYCODE_SUCCESS)
	    {
	      fprintf (stderr,
		       _("%s: punycode_encode() failed with error %d.\n"),
		       argv[0], rc);
	      return 1;
	    }

	  readbuf[len2] = '\0';

	  p = stringprep_utf8_to_locale (readbuf);
	  if (!p)
	    {
	      fprintf (stderr, _("%s: could not convert from UTF-8 to %s.\n"),
		       argv[0], stringprep_locale_charset ());
	      return 1;
	    }

	  fprintf (stdout, "%s\n", p);

	  free (p);
	}

      if (args_info.punycode_decode_given)
	{
	  size_t len;

	  len = BUFSIZ;
	  q = (uint32_t *) malloc (len * sizeof (q[0]));
	  if (!q)
	    {
	      sprintf (readbuf, _("%s: malloc() failed: "), argv[0]);
	      perror (readbuf);
	      return 1;

	    }

	  rc = punycode_decode (strlen (readbuf), readbuf, &len, q, NULL);
	  if (rc != PUNYCODE_SUCCESS)
	    {
	      free (q);
	      fprintf (stderr,
		       _("%s: punycode_decode() failed with error %d.\n"),
		       argv[0], rc);
	      return 1;
	    }

	  if (args_info.debug_given)
	    {
	      size_t i;
	      for (i = 0; i < len; i++)
		fprintf (stderr, _("output[%d] = U+%04x\n"), i, q[i]);
	    }

	  q[len] = 0;
	  r = stringprep_ucs4_to_utf8 (q, -1, NULL, NULL);
	  free (q);
	  if (!r)
	    {
	      fprintf (stderr,
		       _("%s: could not convert from UCS-4 to UTF-8.\n"),
		       argv[0]);
	      return 1;
	    }

	  p = stringprep_utf8_to_locale (r);
	  free (r);
	  if (!r)
	    {
	      fprintf (stderr, _("%s: could not convert from UTF-8 to %s.\n"),
		       argv[0], stringprep_locale_charset ());
	      return 1;
	    }

	  fprintf (stdout, "%s\n", p);

	  free (p);
	}

      if (args_info.idna_to_ascii_given)
	{
	  p = stringprep_locale_to_utf8 (readbuf);
	  if (!p)
	    {
	      fprintf (stderr, _("%s: could not convert from %s to UTF-8.\n"),
		       argv[0], stringprep_locale_charset ());
	      return 1;
	    }
	  q = stringprep_utf8_to_ucs4 (p, -1, NULL);
	  free (p);
	  if (!q)
	    {
	      fprintf (stderr,
		       _("%s: could not convert from UCS-4 to UTF-8.\n"),
		       argv[0]);
	      return 1;
	    }

	  if (args_info.debug_given)
	    {
	      size_t i;
	      for (i = 0; q[i]; i++)
		fprintf (stderr, _("input[%d] = U+%04x\n"), i, q[i]);
	    }

	  rc = idna_to_ascii_4z (q, &p,
				 (args_info.allow_unassigned_given ?
				  IDNA_ALLOW_UNASSIGNED : 0) |
				 (args_info.usestd3asciirules_given ?
				  IDNA_USE_STD3_ASCII_RULES : 0));
	  free (q);
	  if (rc != IDNA_SUCCESS)
	    {
	      fprintf (stderr, _("%s: idna_to_ascii_4z() failed "
				 "with error %d.\n"), argv[0], rc);
	      return 1;
	    }

#ifdef WITH_TLD
	  if (args_info.tld_flag)
	    {
	      size_t errpos;

	      rc = idna_to_unicode_8z4z (p, &q,
					 (args_info.allow_unassigned_given ?
					  IDNA_ALLOW_UNASSIGNED : 0) |
					 (args_info.usestd3asciirules_given ?
					  IDNA_USE_STD3_ASCII_RULES : 0));
	      if (rc != IDNA_SUCCESS)
		{
		  fprintf (stderr, _("%s: TLD idna_to_unicode_8z8z() failed "
				     "with error %d.\n"), argv[0], rc);
		  return 1;
		}

	      if (args_info.debug_given)
		{
		  size_t i;
		  for (i = 0; q[i]; i++)
		    fprintf (stderr, _("tld[%d] = U+%04x\n"), i, q[i]);
		}

	      rc = tld_check_4z (q, &errpos, NULL);
	      if (rc == TLD_INVALID)
		{
		  fprintf (stderr, _("%s: string rejected by TLD test "
				     "(Unicode position %d)\n"), argv[0],
			   errpos);
		  free (q);
		  return 1;
		}
	      if (rc != TLD_SUCCESS)
		{
		  fprintf (stderr,
			   _("%s: tld_check_4z failed with error %d.\n"),
			   argv[0], rc);
		  free (q);
		  return 1;
		}

	      free (r);
	    }
#endif

	  if (args_info.debug_given)
	    {
	      size_t i;
	      for (i = 0; p[i]; i++)
		fprintf (stderr, _("output[%d] = U+%04x\n"), i, p[i]);
	    }

	  fprintf (stdout, "%s\n", p);

	  free (p);
	}

      if (args_info.idna_to_unicode_given)
	{
	  p = stringprep_locale_to_utf8 (readbuf);
	  if (!p)
	    {
	      fprintf (stderr, _("%s: could not convert from %s to UTF-8.\n"),
		       argv[0], stringprep_locale_charset ());
	      return 1;
	    }

	  q = stringprep_utf8_to_ucs4 (p, -1, NULL);
	  if (!q)
	    {
	      free (p);
	      fprintf (stderr,
		       _("%s: could not convert from UCS-4 to UTF-8.\n"),
		       argv[0]);
	      return 1;
	    }

	  if (args_info.debug_given)
	    {
	      size_t i;
	      for (i = 0; q[i]; i++)
		fprintf (stderr, _("input[%d] = U+%04x\n"), i, q[i]);
	    }
	  free (q);

	  rc = idna_to_unicode_8z4z (p, &q,
				     (args_info.allow_unassigned_given ?
				      IDNA_ALLOW_UNASSIGNED : 0) |
				     (args_info.usestd3asciirules_given ?
				      IDNA_USE_STD3_ASCII_RULES : 0));
	  free (p);
	  if (rc != IDNA_SUCCESS)
	    {
	      fprintf (stderr, _("%s: idna_to_unicode_8z4z() "
				 "failed with error %d.\n"), argv[0], rc);
	      return 1;
	    }

	  if (args_info.debug_given)
	    {
	      size_t i;
	      for (i = 0; q[i]; i++)
		fprintf (stderr, _("output[%d] = U+%04x\n"), i, q[i]);
	    }

#ifdef WITH_TLD
	  if (args_info.tld_flag)
	    {
	      size_t errpos;

	      rc = tld_check_4z (q, &errpos, NULL);
	      if (rc == TLD_INVALID)
		{
		  fprintf (stderr, _("%s: string rejected by TLD test "
				     "(Unicode position %d)\n"), argv[0],
			   errpos);
		  free (q);
		  return 1;
		}
	      if (rc != TLD_SUCCESS)
		{
		  fprintf (stderr,
			   _("%s: tld_check_4z failed with error %d.\n"),
			   argv[0], rc);
		  free (q);
		  return 1;
		}
	    }
#endif

	  r = stringprep_ucs4_to_utf8 (q, -1, NULL, NULL);
	  free (q);
	  if (!r)
	    {
	      fprintf (stderr,
		       _("%s: could not convert from UTF-8 to UCS-4.\n"),
		       argv[0]);
	      return 1;
	    }

	  p = stringprep_utf8_to_locale (r);
	  free (r);
	  if (!r)
	    {
	      fprintf (stderr, _("%s: could not convert from UTF-8 to %s.\n"),
		       argv[0], stringprep_locale_charset ());
	      return 1;
	    }

	  fprintf (stdout, "%s\n", p);

	  free (p);
	}
    }
  while (!feof (stdin) && !ferror (stdin) && (args_info.inputs_num == 0 ||
					      cmdn < args_info.inputs_num));

  return 0;
}