Lock page when changes are done in the SQL editor
[phpmyadmin.git] / libraries / Encoding.php
blob8157e1e42271695bd0bdfa6acb15404e4943046f
1 <?php
2 /* vim: set expandtab sw=4 ts=4 sts=4: */
3 /**
4 * Hold the PMA\libraries\Encoding class
6 * @package PhpMyAdmin
7 */
8 namespace PMA\libraries;
10 use PMA\libraries\config\ConfigFile;
12 /**
13 * Encoding conversion helper class
15 * @package PhpMyAdmin
17 class Encoding
19 /**
20 * None encoding conversion engine
22 * @var int
25 const ENGINE_NONE = 0;
26 /**
27 * iconv encoding conversion engine
29 * @var int
31 const ENGINE_ICONV = 1;
33 /**
34 * recode encoding conversion engine
36 * @var int
38 const ENGINE_RECODE = 2;
40 /**
41 * mbstring encoding conversion engine
43 * @var int
45 const ENGINE_MB = 3;
47 /**
48 * Chosen encoding engine
50 * @var int
52 private static $_engine = null;
54 /**
55 * Map of conversion engine configurations
57 * Each entry contains:
59 * - function to detect
60 * - engine contant
61 * - extension name to warn when missing
63 * @var array
65 private static $_enginemap = array(
66 'iconv' => array('iconv', self::ENGINE_ICONV, 'iconv'),
67 'recode' => array('recode_string', self::ENGINE_RECODE, 'recode'),
68 'mb' => array('mb_convert_encoding', self::ENGINE_MB, 'mbstring'),
69 'none' => array('isset', self::ENGINE_NONE, ''),
72 /**
73 * Order of automatic detection of engines
75 * @var array
77 private static $_engineorder = array(
78 'mb', 'iconv', 'recode',
81 /**
82 * Kanji encodings list
84 * @var string
86 private static $_kanji_encodings = 'ASCII,SJIS,EUC-JP,JIS';
88 /**
89 * Initializes encoding engine detecting available backends.
91 * @return void
93 public static function initEngine()
95 $engine = 'auto';
96 if (isset($GLOBALS['cfg']['RecodingEngine'])) {
97 $engine = $GLOBALS['cfg']['RecodingEngine'];
100 /* Use user configuration */
101 if (isset(self::$_enginemap[$engine])) {
102 if (@function_exists(self::$_enginemap[$engine][0])) {
103 self::$_engine = self::$_enginemap[$engine][1];
104 return;
105 } else {
106 PMA_warnMissingExtension(self::$_enginemap[$engine][2]);
110 /* Autodetection */
111 foreach (self::$_engineorder as $engine) {
112 if (@function_exists(self::$_enginemap[$engine][0])) {
113 self::$_engine = self::$_enginemap[$engine][1];
114 return;
118 /* Fallback to none conversion */
119 self::$_engine = self::ENGINE_NONE;
123 * Setter for engine. Use with caution, mostly useful for testing.
125 * @return void
127 public static function setEngine($engine)
129 self::$_engine = $engine;
133 * Checks whether there is any charset conversion supported
135 * @return bool
137 public static function isSupported()
139 if (is_null(self::$_engine)) {
140 self::initEngine();
142 return self::$_engine != self::ENGINE_NONE;
146 * Converts encoding of text according to parameters with detected
147 * conversion function.
149 * @param string $src_charset source charset
150 * @param string $dest_charset target charset
151 * @param string $what what to convert
153 * @return string converted text
155 * @access public
157 public static function convertString($src_charset, $dest_charset, $what)
159 if ($src_charset == $dest_charset) {
160 return $what;
162 if (is_null(self::$_engine)) {
163 self::initEngine();
165 switch (self::$_engine) {
166 case self::ENGINE_RECODE:
167 return recode_string(
168 $src_charset . '..' . $dest_charset,
169 $what
171 case self::ENGINE_ICONV:
172 return iconv(
173 $src_charset,
174 $dest_charset .
175 (isset($GLOBALS['cfg']['IconvExtraParams']) ? $GLOBALS['cfg']['IconvExtraParams'] : ''),
176 $what
178 case self::ENGINE_MB:
179 return mb_convert_encoding(
180 $what,
181 $dest_charset,
182 $src_charset
184 default:
185 return $what;
190 * Detects whether Kanji encoding is available
192 * @return bool
194 public static function canConvertKanji()
196 return (
197 $GLOBALS['lang'] == 'ja' &&
198 function_exists('mb_convert_encoding')
203 * Setter for Kanji encodings. Use with caution, mostly useful for testing.
205 * @return string
207 public static function getKanjiEncodings()
209 return self::$_kanji_encodings;
213 * Setter for Kanji encodings. Use with caution, mostly useful for testing.
215 * @return void
217 public static function setKanjiEncodings($value)
219 self::$_kanji_encodings = $value;
223 * Reverses SJIS & EUC-JP position in the encoding codes list
225 * @return void
227 public static function kanjiChangeOrder()
229 $parts = explode(',', self::$_kanji_encodings);
230 if ($parts[1] == 'EUC-JP') {
231 self::$_kanji_encodings = 'ASCII,SJIS,EUC-JP,JIS';
232 } else {
233 self::$_kanji_encodings = 'ASCII,EUC-JP,SJIS,JIS';
238 * Kanji string encoding convert
240 * @param string $str the string to convert
241 * @param string $enc the destination encoding code
242 * @param string $kana set 'kana' convert to JIS-X208-kana
244 * @return string the converted string
246 public static function kanjiStrConv($str, $enc, $kana)
248 if ($enc == '' && $kana == '') {
249 return $str;
252 $string_encoding = mb_detect_encoding($str, self::$_kanji_encodings);
253 if ($string_encoding === false) {
254 $string_encoding = 'utf-8';
257 if ($kana == 'kana') {
258 $dist = mb_convert_kana($str, 'KV', $string_encoding);
259 $str = $dist;
261 if ($string_encoding != $enc && $enc != '') {
262 $dist = mb_convert_encoding($str, $enc, $string_encoding);
263 } else {
264 $dist = $str;
266 return $dist;
271 * Kanji file encoding convert
273 * @param string $file the name of the file to convert
274 * @param string $enc the destination encoding code
275 * @param string $kana set 'kana' convert to JIS-X208-kana
277 * @return string the name of the converted file
279 public static function kanjiFileConv($file, $enc, $kana)
281 if ($enc == '' && $kana == '') {
282 return $file;
284 $tmpfname = tempnam(ConfigFile::getDefaultTempDirectory(), $enc);
285 $fpd = fopen($tmpfname, 'wb');
286 $fps = fopen($file, 'r');
287 self::kanjiChangeOrder();
288 while (!feof($fps)) {
289 $line = fgets($fps, 4096);
290 $dist = self::kanjiStrConv($line, $enc, $kana);
291 fputs($fpd, $dist);
292 } // end while
293 self::kanjiChangeOrder();
294 fclose($fps);
295 fclose($fpd);
296 unlink($file);
298 return $tmpfname;
302 * Defines radio form fields to switch between encoding modes
304 * @return string xhtml code for the radio controls
306 public static function kanjiEncodingForm()
308 return '<ul><li>'
309 . '<input type="radio" name="knjenc" value="" checked="checked" '
310 . 'id="kj-none" />'
311 . '<label for="kj-none">'
312 /* l10n: This is currently used only in Japanese locales */
313 . _pgettext('None encoding conversion', 'None')
314 . '</label>'
315 . '<input type="radio" name="knjenc" value="EUC-JP" id="kj-euc" />'
316 . '<label for="kj-euc">EUC</label>'
317 . '<input type="radio" name="knjenc" value="SJIS" id="kj-sjis" />'
318 . '<label for="kj-sjis">SJIS</label>'
319 . '</li>'
320 . '<li>'
321 . '<input type="checkbox" name="xkana" value="kana" id="kj-kana" />'
322 . '<label for="kj-kana">'
323 /* l10n: This is currently used only in Japanese locales */
324 . __('Convert to Kana')
325 . '</label><br />'
326 . '</li></ul>';
329 public static function listEncodings()
331 if (is_null(self::$_engine)) {
332 self::initEngine();
334 /* Most engines do not support listing */
335 if (self::$_engine != self::ENGINE_MB) {
336 return $GLOBALS['cfg']['AvailableCharsets'];
339 return array_intersect(
340 array_map('strtolower', mb_list_encodings()),
341 $GLOBALS['cfg']['AvailableCharsets']