protected function detectCharacterEncoding()
    {
        $encoding = null;

        if (function_exists('nl_langinfo') && is_callable('nl_langinfo')) {
            $encoding = nl_langinfo(CODESET);
        } else {
            // try to detect encoding from locale identifier
            $lc_ctype = null;
            $lc_all = self::setlocale(LC_ALL, '0');
            $lc_all_exp = explode(';', $lc_all);
            if (count($lc_all_exp) === 1) {
                $lc_ctype = reset($lc_all_exp);
            } else {
                foreach ($lc_all_exp as $lc) {
                    if (strncmp($lc, 'LC_CTYPE', 8) === 0) {
                        $lc_ctype = $lc;
                        break;
                    }
                }
            }

            if ($lc_ctype !== null) {
                $lc_ctype_exp = explode('.', $lc_ctype, 2);
                if (count($lc_ctype_exp) === 2) {
                    $encoding = $lc_ctype_exp[1];
                }
            }
        }

        // assume encoding is a code-page if encoding is numeric
        if ($encoding !== null && ctype_digit($encoding)) {
            $encoding = 'CP' . $encoding;
        }

        return $encoding;
    }