PHP-IDNA is a native PHP extension that exposes GNU Libidn's Internationalized Domain Name in Applications conversion functions. It converts Unicode domain names to their ASCII-compatible encoding and converts encoded labels back to Unicode.
The source code is available from the PHP-IDNA repository. The extension uses the PHP 5 Zend extension API and links against GNU Libidn. It can be built for compatible PHP environments; another PHP generation requires the corresponding extension-API adaptations.
From Unicode to DNS Labels
The Domain Name System carries ASCII labels. An internationalized domain name lets an application present labels containing non-ASCII characters while using an ASCII-compatible encoding for DNS and protocol operations. An encoded label begins with the ACE prefix xn--; for example, xärg becomes xn--xrg-9ka.
Punycode is the Bootstring encoding defined by RFC 3492. It preserves basic ASCII code points and represents the non-ASCII code points through a compact suffix. Punycode alone is not the complete IDNA procedure. Label mapping, normalization, validity checks, separator handling, and the ACE prefix belong to the surrounding IDNA profile.
PHP-IDNA delegates that complete conversion to GNU Libidn rather than exposing a raw Punycode encoder. The linked library implements the IDNA 2003 model associated with RFC 3490 and Stringprep. Modern IDNA 2008 specifications use revised validity rules, so output and accepted input can differ from current browser or registry processing for some Unicode code points.
Converting Domain Names
The extension registers two functions. Their names in the C function table are idna_toascii() and idna_tounicode(). Each accepts one domain-name string and returns the converted string. A failed Libidn conversion raises a PHP warning and returns false.
<?php
$ascii = idna_toascii('xärg.örg');
$unicode = idna_tounicode('xn--xrg-9ka.xn--rg-eka');
var_dump($ascii);
var_dump($unicode); The example produces:
string(22) "xn--xrg-9ka.xn--rg-eka"
string(10) "xärg.örg" The conversion applies to the complete domain string, so labels separated by dots are handled in one call. The ASCII form is suitable for DNS lookups and protocol fields that require ASCII. The Unicode form is useful when a domain should be displayed to a person.
Runtime Model
PHP-IDNA is a thin wrapper around idna_to_ascii_8z() and idna_to_unicode_8z8z() from GNU Libidn. During module initialization it checks the linked Stringprep version. The module information page reports whether IDNA support is enabled, the extension version, and the GNU Libidn version.
The wrapper passes option flag 0 to Libidn. Conversion behavior therefore follows the IDNA and Stringprep implementation provided by the linked library rather than adding a separate PHP-side normalization or validation layer.
Building the Extension
Install the GNU Libidn development headers before compiling PHP-IDNA. On a Debian-based system the package is commonly named libidn11-dev; other systems may provide it under a different package name.
git clone https://github.com/infusion/PHP-IDNA.git
cd PHP-IDNA
phpize
./configure --with-idna
make
make test
sudo make install Enable the resulting shared module in the applicable PHP configuration:
extension=idna.so config.m4 searches /usr/local and /usr for include/idna.h. A custom installation prefix can be supplied to --with-idna. The configure check also verifies that the idn library exports stringprep_check_version().
Compiling into the PHP source tree
The extension can also be placed in the PHP source tree under ext/idna. Regenerate PHP's configure script with ./buildconf --force, configure PHP with --with-idna, and then build PHP normally.
Input and Display Considerations
- Conversion does not establish that a domain exists or that DNS resolution will succeed.
- Applications should preserve the ASCII form for network operations and treat the Unicode form as display data.
- Do not assume that every string beginning with
xn--is valid merely because it can be decoded. Apply the IDNA profile and application policy before using a label. - GNU Libidn's IDNA 2003 result can differ from IDNA 2008 or compatibility mappings used by browsers and registries. Choose one processing model explicitly when systems must agree.
- Visually similar Unicode characters can produce different domain names. Security-sensitive interfaces should make the canonical ASCII form available when identity matters.
- The linked Libidn version determines the precise normalization and IDNA behavior. Keep that dependency consistent across environments that must produce identical results.
Porting PHP-IDNA
A port to another PHP extension API needs to update parameter parsing, string return handling, module macros, and function metadata while preserving the two Libidn calls and their error semantics. The small wrapper surface makes the conversion behavior straightforward to test with Unicode labels, ASCII labels, multi-label domains, and invalid input.
References
- [Source]PHP-IDNA source repository.
- [Libidn]GNU Libidn, Internationalized Domain Names and Stringprep library.
- [IDNA2003]RFC 3490, Internationalizing Domain Names in Applications.
- [Punycode]RFC 3492, Punycode: A Bootstring encoding of Unicode for Internationalized Domain Names in Applications.
- [IDNA2008]RFC 5890, Internationalized Domain Names for Applications: Definitions and Document Framework.