前日は0時ぐらいまでオフィスでお仕事していて、家に帰ってお風呂入って荷造りして、そのまま寝ないで5時過ぎに出かけて新神戸駅から6時10分発の始発に乗ってから2時間ほど寝た。昼間働いて18時にホテルに戻ってまた2-3時間ほど寝て晩ご飯食べてから2時間ほどお仕事していた。寝付けなくて3時ぐらいに起きて吐いた。吐いたら気分よくなってその後はよく眠れた。

windows の内部の文字の扱い

前日の日曜日に実装したツールをメンバーに windows server検証してもらう。ある変換処理で windows の内部では文字を utf16le で扱っていて、文字コード変換の処理が漏れていることに気付いた。go の準標準ライブラリを使って、次のようなコードで utf16le から utf8 への変換ができる。

import "golang.org/x/text/encoding/unicode"

decoded, err := unicode.UTF16(unicode.LittleEndian, unicode.IgnoreBOM).NewDecoder().Bytes(b)

LDAP の DN の仕様

LDAP の distinguished name (DN) を調べた。例えば、windows で dn を powershell の Get-ADUser を使って取得すると次のような値を取得できる。

dn="CN=Test,CN=Users,DC=example,DC=com"

CNDC は大文字/小文字どちらでもよいが、それが違うと dn の値として別の値になってしまう。できれば小文字に統一したい。その変換処理を実装しようと思って仕様を調べていたら RFC-4514 Lightweight Directory Access Protocol (LDAP): String Representation of Distinguished Names で定義されていることがわかった。ここで定義されている特殊な文字、例えばカンマや等号などはエスケープして値としても使えるように書いてある。キーの値を変換するにはこれらの仕様を理解してパースして変換しないといけない。わりと大変なことを理解して go-ldap のライブラリのコードを読んでいたら正に ParseDN() がそんな実装になっていた。

func ParseDN(str string) (*DN, error)

このツールを使って dn インスタンスにパースして文字列表現を取得すると自動的に正規化されて小文字に変換してくれる。

dn, err := ldap.ParseDN(s)
if err != nil {
    return fmt.Errorf("failed to parse dn: %w", err)
}
dn.String()