メインコンテンツへジャンプする

JPNICはインターネットの円滑な運営を支えるための組織です

ロゴ:JPNIC

WHOIS 検索 サイト内検索 WHOISとは? JPNIC WHOIS Gateway
WHOIS検索 サイト内検索

idnkit ライブラリの API

idnkit ライブラリでは、アプリケーションを国際化ドメイン名に対応させる ために必要な処理を API として提供しています。 この文書は、ライブラリの提供する API について解説します。


概要

国際化ドメイン名の処理は次の3つの処理から構成されます。

  • エンコーディング変換
  • デリミタマッピング
  • NAMEPREP

idnkit では、これに加えて地域化のために

  • トップレベルドメインに基づくローカルマッピング

という処理を追加しています。

国際化ドメイン処理のアーキテクチャ IDNA では、これらの処理はすべてアプリケーションで行うことになっており、 例えば名前解決用の関数 gethostbyname を呼び出して 国際化ドメイン名の名前解決を行う場合には、 すでにこれらの処理が行われた結果の文字列を渡すことになっています。

idnkit はアプリケーションでこれらの処理を行うために 2種類の API を用意しています。

高レベル API
一般アプリケーションのためのシンプルで使いやすい API です。 この API を使用すれば、アプリケーションに簡単に国際化ドメイン処理機能を 追加することができます。ただし細かい設定などはできません。
低レベル API
高レベル API ではできないような細かい設定をする必要がある 一部の特殊なアプリケーションのための API です。 高レベル API はこの低レベル API の上に作られています。

低レベル API は特殊なアプリケーションのために用意された API ですので、 ここでは説明しません。もし低レベル API を使用したい場合には、 idnkit ライブラリ仕様書resconfモジュール および resモジュール をご覧ください。

高レベル API は次の3つの関数から構成されます。

  1. 初期化を行う idn_nameinit
  2. 名前解決などのために国際化ドメイン名をエンコードする idn_encodename
  3. DNS サーバなどから返ってきた国際化ドメイン名をデコードする idn_decodename

以下、それぞれの関数の説明をします。 idnkit ライブラリ仕様書の apiモジュール も合わせてご覧ください。


初期化

国際化ドメイン名の処理のための初期化を行うためには idn_nameinit を用います。

idn_result_t idn_nameinit(int load_file)

高レベル API モジュールの初期化を行います。

load_file に 0 以外の値を指定すると、 設定ファイル を読み込みます。

load_file に 0 を指定すると、設定ファイルを全く参照せず、 標準の設定 (IDN エンコーディングに Punycode、NAMEPREP に最新バージョン を指定) を使って初期化が行われます。

この関数は戻り値として実行結果を示す idn_result_t 型の値を返します。 本関数が返すコードとその意味は次の通りです。

idn_success
初期化が正常に終了した。
idn_nofile
設定ファイルがオープンできなかった。
idn_invalid_syntax
設定ファイルにシンタックスエラーがある。
idn_invalid_name
設定ファイルに指定されている名前 (エンコーディング名など) に誤りがある。
idn_nomemory
malloc に失敗した。

この関数を複数回呼び出すこともできますが、初期化が行われるのは初回の 呼び出しの時だけで、2 回目以降は何も行われません。

この関数をあらかじめ呼び出さずにエンコードやデコード関数を 呼び出しても構いません。その場合には、エンコードやデコードの処理に 先立って、idn_nameinit(0) による初期化が暗黙的に行われます。


エンコード

国際化ドメイン名のエンコード処理、つまり名前解決関数などへ渡すための 文字列に変換するには idn_encodename を用います。

idn_result_t idn_encodename(idn_action_t actions, const char *from,
                            char *to, size_t tolen)

引数 actions には、エンコード処理のどの工程を実行するかを 指定します。 通常のエンコード処理では、クエリー時に必要なすべての工程を行うことを示す IDN_ENCODE_APP というマクロの値を指定することになります。

特定の工程だけ処理したい場合は、各処理工程を表すマクロ値の論理和 (OR) を指定します。 用意されているマクロは次の通りです。 なお、各処理はここに挙げた順番で行われます。

IDN_LOCALCONV
ローカルエンコーディングから UTF-8 への変換を行う
IDN_DELIMMAP
デリミタマッピングを行う
IDN_LOCALMAP
トップレベルドメインに基づくローカルマッピングを行う
IDN_NAMEPREP
NAMEPREP (国際化ドメイン名の正規化、禁止文字の検出など) を行う
IDN_UNASCHECK
未割り当てコードポイントのチェックを行う。
IDN_ASCCHECK
ASCII 文字に関するチェック (英数字やハイフン以外の文字の有無など) を行う。
IDN_IDNCONV
UTF-8 から IDN エンコーディングへの変換を行う
IDN_LENCHECK
ドメイン名の各ラベルの長さをチェックする。

from で指定されるドメイン名に対して、actions で 指定された処理を行い、その結果を to の指す領域に書き込みます。 tolento の指す領域の大きさ (バイト数、末尾の ナル文字を含む) で、tolen を越えて書き込むことはありません。

この関数は戻り値として実行結果を示す idn_result_t 型の値を返します。 本関数が返すコードとその意味は次の通りです。

idn_success
処理が正常に終了した。
idn_invalid_action
actions で誤ったフラグを指定している。
idn_invalid_encoding
from で指定された文字列のエンコーディングに誤りがある。
idn_invalid_length
変換した結果、いずれかのラベルの長さが範囲外になった。
idn_prohibited
入力文字列中に禁止文字あるいは Unicode の未割り当てコードポイントが 存在する。
idn_buffer_overflow
tolen の値が小さすぎて結果を格納できない。
idn_nomemory
malloc に失敗した。

なお、初期化関数 idn_nameinit を事前に呼び出さずに 本関数を呼び出した場合には、上に示した他に次のような実行結果を返す ことがあります。

idn_nofile
設定ファイルがオープンできなかった。
idn_invalid_syntax
設定ファイルにシンタックスエラーがある。
idn_invalid_name
設定ファイルに指定されている名前 (エンコーディング名など) に 誤りがある。

なお、設定によっては、この関数を使用しても文字列の変換は行われず、 元の文字列のままの結果が返されることがあります。 詳しくは 環境変数 IDN_DISABLE のオーバーライド をご覧ください。


デコード

国際化ドメイン名のデコード処理、つまり名前解決関数などから返された IDN エンコーディングのドメイン名文字列を、アプリケーションが使用 しているローカルエンコーディングに変換するには idn_decodename を用います。

idn_result_t idn_decodename(idn_action_t actions, const char *from,
                            char *to, size_t tolen)

引数 actions には、デコード処理のどの工程を実行するかを 指定します。 通常のデコード処理では、すべての工程を行うことを示す IDN_DECODE_APP というマクロの値を指定することになります。

特定の工程だけ処理したい場合は、各処理工程を表すマクロ値の論理和 (OR) を指定します。 用意されているマクロは次の通りです。 なお、各処理はここに挙げた順番で行われます。

IDN_DELIMMAP
デリミタマッピングを行う
IDN_NAMEPREP
NAMEPREP (国際化ドメイン名の正規化、禁止文字の検出など) を行う
IDN_UNASCHECK
未割り当てコードポイントのチェックを行う。
IDN_IDNCONV
IDN エンコーディングから UTF-8 への変換を行う
IDN_RTCHECK
国際化ドメイン名が正しくエンコードされたものかどうかを調べるために、 再びエンコードして一致するかどうか確認する。 一致しなかった場合は IDN エンコーディングへ戻す。 一致した場合は UTF-8 のまま。
IDN_ASCCHECK
ラウンドトリップチェック時に、ASCII 文字に関するチェック (英数字やハイフン以外の文字の有無など) を行う。
IDN_LOCALCONV
UTF-8 からローカルエンコーディングへの変換を行う。 ただしローカルエンコーディングに対応する文字がないために 変換不可能な場合には、IDN エンコーディングへの変換を行う。

from で指定されるドメイン名に対して、actions で 指定される処理を行い、その結果を to の指す領域に書き込みます。 tolento の指す領域の大きさ (バイト数、末尾の ナル文字を含む) で、tolen を越えて書き込むことはありません。

なお、上記の各処理でのパラメータはすべて idnkit の 設定ファイル で設定されたものが使用されます。 以下に使用されるパラメータを記します。

  • IDN エンコーディングとして使用するエンコーディング名
  • NAMEPREP のバージョン

この関数は戻り値として実行結果を示す idn_result_t 型の値を返します。 本関数が返すコードとその意味は次の通りです。

idn_success
処理が正常に終了した。
idn_invalid_action
actions で誤ったフラグを指定している。
idn_invalid_encoding
from で指定された文字列のエンコーディングに誤りがある。
idn_buffer_overflow
tolen の値が小さすぎて結果を格納できない。
idn_nomemory
malloc に失敗した。

なお、初期化関数 idn_nameinit を事前に呼び出さずに 本関数を呼び出した場合には、上に示した他に次のような実行結果を返す ことがあります。

idn_nofile
設定ファイルがオープンできなかった。
idn_invalid_syntax
設定ファイルにシンタックスエラーがある。
idn_invalid_name
設定ファイルに指定されている名前 (エンコーディング名など) に 誤りがある。

なお、設定によっては、この関数を使用しても文字列の変換は行われず、 元の文字列のままの結果が返されることがあります。 詳しくは 環境変数 IDN_DISABLE のオーバーライド をご覧ください。


環境変数 IDN_DISABLE のオーバーライド

通常の場合、 環境変数 IDN_DISABLE が設定されている環境でドメイン名をエンコード、デコードしても変換処理は 実行されず、元の文字列のまま結果が返されます。 ただし、この設定を明示的にオーバーライドするための API として、 idn_enableが用意されています。

void
idn_enable(int on_off)

環境変数 IDN_DISABLE が設定されているかどうかにかかわらず、 on_off が 0 の場合、これ以降のドメイン名変換は行われません。 また、on_off が 0 以外の値であれば、この関数の呼び出し以降は IDN_DISABLE 環境変数が設定されているかどうかにかかわらず、ドメイン名変換 処理が行われます。


プログラム作成方法

上記の API を使用したプログラムを作る方法、および注意点などについて まとめておきます。

  • インクルードファイル
    高レベル API を使用するプログラムでは、stddef.hidn/api.h の2つのヘッダファイルをインクルードしてください。
    #include <stddef.h>
    #include <idn/api.h>
    
  • ロケール設定
    idnkit はアプリケーションの使用しているローカルエンコーディングを ロケール情報、あるいは環境変数 IDN_LOCAL_CODESET から 取得します。ロケール情報から取得する場合にはアプリケーションの先頭で setlocale を行い、アプリケーションのロケールを正しく 設定してください。
  • エラー表示
    API はいずれも idn_result_t 型の値を返します。この値から 対応するメッセージ文字列を得るための関数 idn_result_tostring が用意されています。エラーメッセージを表示する際に使うことができます。 この関数については 仕様書の説明をご覧ください。
  • コンパイルとリンク
    コンパイルする際には、-I オプションで idnkit の ヘッダファイルのインストールディレクトリ (デフォルトでは /usr/local/include) を指定してください。
    またリンクの際は idnkit ライブラリをリンクしてください。もし iconv が標準ライブラリにない場合には、iconv の ライブラリも合わせてリンクしてください。
    cc -I/usr/local/include example.c -L/usr/local/lib -lidn -liconv
    

プログラム例

ここでは、上記の API を使用して国際化ドメイン名の名前解決を行うための 簡単なプログラムを紹介します。

#include <stdio.h>
#include <stddef.h>
#include <netdb.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <idn/api.h>

int main(int ac, char **av)
{
    struct hostent *hp;
    char buf1[256];
    char buf2[256];
    char addrbuf[100];
    idn_result_t r;

    /* ロケールを設定する */
    setlocale(LC_ALL, "");
    if (ac != 2) {
        fprintf(stderr, "Usage: %s hostname\n", av[0]);
        return 1;
    }
    /* api モジュールを初期化する */
    if ((r = idn_nameinit(1)) != != idn_success) {
        fprintf(stderr, "idn_nameinit: %s\n", idn_result_tostring(r));
        return 1;
    }
    /* gethostbyname を呼ぶ前に名前を変換する */
    if ((r = idn_encodename(IDN_ENCODE_APP, av[1],
                            buf1, sizeof(buf1))) != idn_success) {
        fprintf(stderr, "idn_encodename: %s\n", idn_result_tostring(r));
        return 1;
    }
    /* 名前解決を行う */
    if ((hp = gethostbyname(buf1)) == NULL) {
        fprintf(stderr, "gethostbyname failed\n");
        return 1;
    }
    /* 返された名前をローカルエンコーディングに変換する */
    if ((r = idn_decodename(IDN_DECODE_APP, hp->h_name,
                            buf2, sizeof(buf2))) != idn_success) {
        fprintf(stderr, "idn_decodename: %s\n", idn_result_tostring(r));
        return 1;
    }
    printf("%s  %s\n",
           inet_ntop(hp->h_addrtype, hp->h_addr, addrbuf, sizeof(addrbuf)),
           buf2);
    return 0;
}

このページを評価してください

このWebページは役に立ちましたか?
ページの改良点等がございましたら自由にご記入ください。

このフォームをご利用した場合、ご連絡先の記入がないと、 回答を差し上げられません。 回答が必要な場合は、お問い合わせ先をご利用ください。

ロゴ:JPNIC

Copyright© 1996-2019 Japan Network Information Center. All Rights Reserved.