/** * g_hostname_to_ascii: * @hostname: a valid UTF-8 or ASCII hostname * * Converts @hostname to its canonical ASCII form; an ASCII-only * string containing no uppercase letters and not ending with a * trailing dot. * * Return value: an ASCII hostname, which must be freed, or %NULL if * @hostname is in some way invalid. * * Since: 2.22 **/ gchar * g_hostname_to_ascii (const gchar *hostname) { gchar *name, *label, *p; GString *out; gssize llen, oldlen; gboolean unicode; label = name = nameprep (hostname, -1, &unicode); if (!name || !unicode) return name; out = g_string_new (NULL); do { unicode = FALSE; for (p = label; *p && !idna_is_dot (p); p++) { if ((guchar)*p > 0x80) unicode = TRUE; } oldlen = out->len; llen = p - label; if (unicode) { if (!strncmp (label, IDNA_ACE_PREFIX, IDNA_ACE_PREFIX_LEN)) goto fail; g_string_append (out, IDNA_ACE_PREFIX); if (!punycode_encode (label, llen, out)) goto fail; } else g_string_append_len (out, label, llen); if (out->len - oldlen > 63) goto fail; label += llen; if (*label) label = g_utf8_next_char (label); if (*label) g_string_append_c (out, '.'); } while (*label); g_free (name); return g_string_free (out, FALSE); fail: g_free (name); g_string_free (out, TRUE); return NULL; }
/** * g_hostname_to_unicode: * @hostname: a valid UTF-8 or ASCII hostname * * Converts @hostname to its canonical presentation form; a UTF-8 * string in Unicode normalization form C, containing no uppercase * letters, no forbidden characters, and no ASCII-encoded segments, * and not ending with a trailing dot. * * Of course if @hostname is not an internationalized hostname, then * the canonical presentation form will be entirely ASCII. * * Return value: a UTF-8 hostname, which must be freed, or %NULL if * @hostname is in some way invalid. * * Since: 2.22 **/ gchar * g_hostname_to_unicode (const gchar *hostname) { GString *out; gssize llen; out = g_string_new (NULL); do { llen = idna_end_of_label (hostname) - hostname; if (!g_ascii_strncasecmp (hostname, IDNA_ACE_PREFIX, IDNA_ACE_PREFIX_LEN)) { hostname += IDNA_ACE_PREFIX_LEN; llen -= IDNA_ACE_PREFIX_LEN; if (!punycode_decode (hostname, llen, out)) { g_string_free (out, TRUE); return NULL; } } else { gboolean unicode; gchar *canonicalized = nameprep (hostname, llen, &unicode); if (!canonicalized) { g_string_free (out, TRUE); return NULL; } g_string_append (out, canonicalized); g_free (canonicalized); } hostname += llen; if (*hostname) hostname = g_utf8_next_char (hostname); if (*hostname) g_string_append_c (out, '.'); } while (*hostname); return g_string_free (out, FALSE); }
/** * g_hostname_to_unicode: * @hostname: a valid UTF-8 or ASCII hostname * * Converts @hostname to its canonical presentation form; a UTF-8 * string in Unicode normalization form C, containing no uppercase * letters, no forbidden characters, and no ASCII-encoded segments, * and not ending with a trailing dot. * * Of course if @hostname is not an internationalized hostname, then * the canonical presentation form will be entirely ASCII. * * Return value: a UTF-8 hostname, which must be freed, or %NULL if * @hostname is in some way invalid. * * Since: 2.22 **/ gchar * g_hostname_to_unicode (const gchar *hostname) { GString *out; gssize llen; out = g_string_new (NULL); do { llen = strcspn (hostname, "."); if (!g_ascii_strncasecmp (hostname, IDNA_ACE_PREFIX, IDNA_ACE_PREFIX_LEN)) { hostname += IDNA_ACE_PREFIX_LEN; llen -= IDNA_ACE_PREFIX_LEN; if (!punycode_decode (hostname, llen, out)) { g_string_free (out, TRUE); return NULL; } } else { gchar *canonicalized = nameprep (hostname, llen); if (!canonicalized) { g_string_free (out, TRUE); return NULL; } g_string_append (out, canonicalized); g_free (canonicalized); } hostname += llen; if (*hostname && *++hostname) g_string_append_c (out, '.'); } while (*hostname); return g_string_free (out, FALSE); }