<?php

class Xoonips_Utils {

	public static function convertSQLStr($v) {
		if (is_null($v)) {
			$ret = 'NULL';
		} elseif ($v === '') {
			$ret = "''";
		} else {
			$v = addslashes($v);
			$ret = "'$v'";
		}
		return $ret;
	}

	public static function convertSQLStrLike($v) {
		if (is_null($v)) {
			$ret = 'NULL';
		} elseif ($v === '') {
			$ret = '';
		} else {
			$v = addslashes($v);
			$v = str_replace("_", "\\_", $v);
			$v = str_replace("%", "\\%", $v);
			$ret = "$v";
		}
		return $ret;
	}

	public static function convertSQLNum($v) {
		if (is_numeric($v)) {
			if(is_float($v)) {
				$ret = floatval($v);
			} else {
				$ret = intval($v);
			}
		} else {
			$ret = 'NULL';
		}
		
		return $ret;
	}

	public static function convertMsgSign($dirname, $trustDirname) {
		$config_keys = array('message_sign' => 's');
		$config_values = self::xoonipsAdminGetConfigs($config_keys, 'e', $dirname, $trustDirname);
		$myxoopsConfig = Xoonips_Utils::getXoopsConfigs(XOOPS_CONF);
		$config_values = array(
			'sitename' =>  $myxoopsConfig['sitename'],
			'adminmail' => $myxoopsConfig['adminmail'],
			'siteurl' => XOOPS_URL . '/',
			'message_sign' => $config_values['message_sign'],
		);
		return $config_values;
	}

	public static function xoonipsAdminGetConfigs($keys, $fmt, $dirname, $trustDirname) {
		$configBean = Xoonips_BeanFactory::getBean('ConfigBean', $dirname, $trustDirname);
		$ret = array();
		foreach ($keys as $key => $key_fmt) {
			$val = $configBean->getConfig($key);
			if (is_null($val)) {
				$ret[$key] = $val;
			} else {
				switch ($key_fmt) {
					case 's':
						// string
						switch ($fmt) {
							case 's':
							case 'show':
							case 'e':
							case 'edit':
								$ret[$key] = $val;
								break;
							case 'n':
							case 'none':
								$ret[$key] = $val;
						}
						break;
					case 'i':
						// int
						$ret[$key] = intval($val);
						break;
					case 'f':
						// float
						$ret[$key] = floatval($val);
						break;
					default:
						die('unknown key type');
				}
			}
		}
		return $ret;
	}

	public static function xoonipsAdminGetRequests($method, $keys) {
		global $xoonips_admin;
		$request = new Xoonips_Request();
		$ret = array();
		foreach ($keys as $key => $attributes) {
			list($type, $is_array, $required) = $attributes;
			$value = $request->getParameter($key);
			$ret[$key] = $value;
		}
		return $ret;
	}

	public static function xoonipsAdminSetConfig($key, &$val, $type, $dirname, $trustDirname) {
		$myts = & MyTextSanitizer::getInstance();
		$configBean = Xoonips_BeanFactory::getBean('ConfigBean', $dirname, $trustDirname);
		$cleanv = null;
		switch ($type) {
		case 's':
			// string
			$cleanv = $myts->censorString($val);
			break;
		case 'i':
			// int
			$cleanv = intval($val);
			break;
		case 'f':
			// float
			$cleanv = floatval($val);
			break;
		}
		if (is_null($cleanv)) {
			return false;
		}
		return $configBean->updateConfig( $key, $cleanv );
	}

	public static function convertPost($post, $layered = false) {
		$ret = array();
		foreach ($post as $key => $val) {
			if (is_array($val)) {
				foreach ($val as $k => $v) {
					$ret[$key][$k] = self::convertToNumericEntities($v, $layered);
				}
			} else {
				$ret[$key] = self::convertToNumericEntities($val, $layered);
			}
		}
		return $ret;
	}

	/**
	 * convert string to numeric entities
	 *  - html entities => numeric entities
	 *  - 3 byte EUC => numeric entities
	 *
	 * @access public
	 * @param string $val
	 * @param boolean $layered
	 * @return string converted string
	 */
	public static function convertToNumericEntities($val, $layered = false) {
		// convert html character entity references to numeric character references
		$val = self::htmlNumericEntities($val);

		if ($layered) {
			$val = self::decodeUtf8($val, _CHARSET, 'h');
		} else {
			// convert JIS X 0212 to numeric character reference
			if (_CHARSET == 'EUC-JP') {
				$len = strlen($val);
				$chars = array();
				$convmap = array(0x0, 0xffff, 0, 0xffff);
				for ($i = 0; $i < $len; $i++) {
					if (ord($val[$i]) <= 127) {
						$chars[] = $val[$i];
					} elseif (ord($val[$i]) != 0x8f) {
						$chars[] = substr($val, $i, 2);
						$i++;
					} else {
						$chars[] = mb_encode_numericentity(substr($val, $i, 3), $convmap, 'EUC-JP');
						$i += 2;
					}
				}
				$val = implode('', $chars);
			}
		}
		return $val;
	}

	/**
	 * delete files not related to any sessions and any items.
	 * @access public
	 */
	public static function cleanup($dirname) {
		global $xoopsDB;
		$fileTable = $xoopsDB->prefix($dirname . '_item_file');
		$sessionTable = $xoopsDB->prefix('session');
		$searchTextTable = $xoopsDB->prefix($dirname . '_search_text');
		// remove file if no-related sessions and files
		$sql = "select file_id from $fileTable as tf left join $sessionTable as ts on tf.sess_id=ts.sess_id where tf.item_id is NULL and ts.sess_id is NULL";
		$result = $xoopsDB->query($sql);
		while (list($file_id) = $xoopsDB->fetchRow($result)) {
			$path = getUploadFilePath($file_id);
			if (is_file($path)) {
				unlink($path);
			}
			$xoopsDB->queryF("delete from $searchTextTable where file_id=$file_id");
			$xoopsDB->queryF("delete from $fileTable where file_id=$file_id");
		}
	}

	public static function getAcceptCharset() {
		if (_CHARSET == 'ISO-8859-1') {
			$accept_charset = ' accept-charset="UTF-8"';
		} else {
			$accept_charset = '';
		}
		return $accept_charset;
	}

	/**
	 * get creative commons license
	 *
	 * @access public
	 * @param int $cc_commercial_use
	 * @param int $cc_modification
	 * @param float $version
	 * @param string $region
	 * @return string rendlerd creative commons licnese
	 */
	public static function getCcLicense($cc_commercial_use, $cc_modification, $version, $region) {
		static $cc_condition_map = array(
			'00' => 'BY-NC-ND',
			'01' => 'BY-NC-SA',
			'02' => 'BY-NC',
			'10' => 'BY-ND',
			'11' => 'BY-SA',
			'12' => 'BY',
		);
		static $cc_region_map = array(
			'GENERIC' => array('25')
		);
		static $cc_cache = array();
		$condition = sprintf('%u%u', $cc_commercial_use, $cc_modification);
		$region = strtoupper($region);
		$version = sprintf('%u', $version * 10);
		if (!isset($cc_condition_map[$condition])) {
			// unknown condtion
			return false;
		}
		$condition = $cc_condition_map[$condition];

		if (isset($cc_cache[$region][$condition])) {
			return $cc_cache[$region][$condition];
		}
		$reg = sprintf('/\bCC\-%s-\d{2}-%s\.html\b/', $condition, $region);
		$fpath = self::ccTemplateDir(XOONIPS_TRUST_DIRNAME);
		$fileNames = scandir($fpath);
		if (!$fileNames) {
			return false;
		}
		$fname = '';
		foreach ($fileNames as $fileName) {
			if (preg_match($reg, $fileName, $matches) == 1) {
				$fname = $fileName;
				break;
			}
		}
		if ($fname == '') {
			return false;
		}
		$fpath = self::ccTemplateDir(XOONIPS_TRUST_DIRNAME) . $fname;
		// file not found
		if (!file_exists($fpath)) {
			return false;
		}
		$cc_html = @file_get_contents($fpath);
		// failed to read file
		if ($cc_html === false) {
			return false;
		}
		$cc_cache[$region][$version][$condition] = $cc_html;
		return $cc_html;
	}

	/**
	 * Finds whether a USER can export.
	 * It regards $xoopsUser as USER.
	 *
	 * @access public
	 * @param string $dirname
	 * @param string $trustDirname
	 * @return bool true if export is permitted for USER.
	 */
	public static function isUserExportEnabled($dirname, $trustDirname) {
		global $xoopsUser;

		if (!$xoopsUser) {
			return false;//guest can not export
		}

		$userBean = Xoonips_BeanFactory::getBean('UsersBean', XCUBE_CORE_USER_MODULE_NAME);
		if ($userBean->isModerator($xoopsUser->getVar('uid'))) {
			return true; //moderator can always export
		}

		$configBean = Xoonips_BeanFactory::getBean('ConfigBean', $dirname, $trustDirname);
		$export_enabled = $configBean->getConfig('export_enabled');
		if (is_null($export_enabled)) {
			return false;
		}

		//see xoonips_config setting for other users
		return $export_enabled == 'on';
	}

	/**
	 * deny guest access and redirect
	 *
	 * @param string $url redurect URL(default is modules/user.php)
	 * @param string $msg message of redirect(default is _MD_XOONIPS_ITEM_FORBIDDEN)
	 */
	public static function denyGuestAccess($url = null, $msg = null) {
		global $xoopsUser;
		global $xoopsModule;
  		$msg = constant('_MD_' . strtoupper($xoopsModule->getVar('trust_dirname')) . '_ITEM_FORBIDDEN');
		if (!$xoopsUser) redirect_header(is_null($url) ? XOOPS_URL . '/user.php' : $url, 3, $msg);
	}

	/**
	 * get server character set.
	 * XOOPS character set 'ISO-8859-1' is treated as Windows-1252.
	 * @access public
	 * @return character set name
	 */
	public static function getServerCharset() {
		if (_CHARSET == 'ISO-8859-1') {
			return 'Windows-1252';
		} else {
			return _CHARSET;
		}
	}
		/**
	 * detect browser encoding.
	 * @access private
	 * @return encoding name
	 */
	private static function detectBrowserEncoding() {
		$encoding = 'ASCII';
		$ua = isset($_SERVER['HTTP_USER_AGENT']) ? $_SERVER['HTTP_USER_AGENT'] : '';
		$lang = isset($_SERVER['HTTP_ACCEPT_LANGUAGE']) ? $_SERVER['HTTP_ACCEPT_LANGUAGE'] : '';
		if (strstr($ua, 'Mac OS X')) {
			$encoding = 'UTF-8';
		} elseif (strstr($ua, 'Windows')) {
			if (strstr($ua, 'MSIE' ) || strstr($ua, 'Gecko')) {
				if (strstr($lang, 'ja')) {
					// for japanese
					$encoding = 'SJIS-win';
				} elseif (strstr($lang, 'en')) {
					// for english
					$encoding = 'Windows-1252';
				}
			}
		}
		return $encoding;
	}

	/**
	 * convert file name
	 * @access public
	 * @param string $filename
	 */
	public static function convertFilename($filename) {
		$ua = isset($_SERVER['HTTP_USER_AGENT']) ? $_SERVER['HTTP_USER_AGENT'] : '';
		$browser_encoding = Xoonips_Utils::detectBrowserEncoding();
		if (strstr($ua, 'MSIE')) {
			$client_filename = Xoonips_Utils::decodeUtf8(Xoonips_Utils::encodeUtf8($filename), $browser_encoding, 'u');
			$utf8_client_filename = Xoonips_Utils::encodeUtf8($client_filename, $browser_encoding);
			return urlencode($utf8_client_filename);
		} elseif (strstr($ua, 'KHTML')) {
			return '';
		} elseif (strstr($ua, 'Gecko') || strstr($ua, 'Mac OS X')) {
			$client_filename = Xoonips_Utils::decodeUtf8(Xoonips_Utils::encodeUtf8($filename), $browser_encoding, 'u');
			$mime_encoding = $browser_encoding;
			$internal_encoding_orig = mb_internal_encoding();
			if (!@mb_internal_encoding($browser_encoding)) {
				if ($browser_encoding == 'SJIS-win') {
					mb_internal_encoding('Shift_JIS');
				} else {
					$client_filename = Xoonips_Utils::decodeUtf8(Xoonips_Utils::encodeUtf8($filename), 'ASCII', 'u');
					mb_internal_encoding('ASCII');
					$mime_encoding = 'ASCII';
				}
			}
			$mime_client_filename = mb_encode_mimeheader($client_filename, $mime_encoding, 'B');
			mb_internal_encoding($internal_encoding_orig);
			return $mime_client_filename;
		} else {
			// unknown browsers
			return Xoonips_Utils::decodeUtf8(Xoonips_Utils::encodeUtf8($filename), 'ASCII', 'u');
		}
	}

	public static function convertToClient($text) {
		return Xoonips_Utils::decodeUtf8(Xoonips_Utils::encodeUtf8($text), Xoonips_Utils::detectBrowserEncoding(), 'u');
	}

	/**
	 * get xoops configs for compatibility with XOOPS Cube Legacy 2.1
	 * @access public
	 * @return array xoops configs
	 */
	public static function getXoopsConfigs($category) {
		static $cache_configs = array();
		if (isset($cache_configs[$category])) {
			return $cache_configs[$category];
		}
		$config_handler =& xoops_gethandler('config');
		$configs = $config_handler->getConfigsByCat($category);
		switch ($category) {
			case XOOPS_CONF:
				$tmp =& $config_handler->getConfigsByDirname('legacyRender');
				$configs['banners'] = $tmp['banners'];
				$tmp =& $config_handler->getConfigsByDirname(XCUBE_CORE_USER_MODULE_NAME);
				$configs['usercookie'] = $tmp['usercookie'];
				$configs['maxuname'] = $tmp['maxuname'];
				$configs['sslloginlink'] = $tmp['sslloginlink'];
				$configs['sslpost_name'] = $tmp['sslpost_name'];
				$configs['use_ssl'] = $tmp['use_ssl'];
				break;
			case XOOPS_CONF_USER:
				$configs = $config_handler->getConfigsByDirname(XCUBE_CORE_USER_MODULE_NAME);
				break;
		}
		$cache_configs[$category] =& $configs;
		return $cache_configs[$category];
	}

	/**
	 * escape html special characters
	 * this function will convert text to follow some rules:
	 * - '&' => '&amp;'
	 * - '"' => '&quot;'
	 * - ''' => '&#039;'
	 * - '<' => '&lt;'
	 * - '>' => '&gt;'
	 * - numeric entity reference => (pass)
	 * - character entity reference => (pass)
	 * - '&nbsp;' => '&amp;nbsp;'
	 *
	 * @access public
	 * @param string $text text string
	 * @return string escaped text string
	 */
	public static function htmlSpecialChars($text) {
		static $s = array(
			'/&amp;#([xX][0-9a-fA-F]+|[0-9]+);/',
			'/&amp;([a-zA-Z][0-9a-zA-Z]+);/e',
			'/&nbsp;/'
		);
		static $r = array(
			'&#\\1;',
			'in_array("&$1;", self::getCharRef()) ? "&$1;" : "&amp;$1;"',
			'&amp;nbsp;'
		);
		return preg_replace($s, $r, htmlspecialchars($text, ENT_QUOTES));
	}

	/**
	 * convert text to UTF-8 string with predefined five xml entitities
	 * - predefined five xml entities are: &amp; &lt; &gt; &apos; &quot;
	 *
	 * @access public
	 * @param string $text input string
	 * @param string $enc text encoding
	 * @return string UTF-8 string with predefined five xml entities
	 */
	public static function xmlSpecialChars($text, $enc = '') {
		$text = self::encodeUtf8($text, $enc);
		// html character entity reference to html numeric entity reference
		$text = str_replace(self::getCharRef(), self::getNumericRef(), $text);
		// convert '&' to '&amp;' for mb_decode_numericentity()
		$text = preg_replace('/&/', '&amp;', $text);
		// convert numeric entity of hex type to dec type
		$text = preg_replace(array('/&amp;#[xX]([0-9a-fA-F]+);/e', '/&amp;#([0-9]+);/'), array('"&#".hexdec("$1").";"', '&#$1;'), $text);
		// decode numeric entity
		$text = mb_decode_numericentity($text, array(0x0, 0x10000, 0, 0xfffff), 'UTF-8');
		// convert &amp; to '&' for htmlspecialchars()
		$text = preg_replace('/&amp;/', '&', $text);
		// eacape html special character
		$text = htmlspecialchars($text, ENT_QUOTES, 'UTF-8');
		// trim control character and convert &#039; to &apos;
		return preg_replace(array('/[\\x00-\\x09\\x0b\\x0c\\x0e-\\x1f\\x7f]/', '/&#039;/'), array('', '&apos;'), $text);
	}

	/**
	 * convert encoding to UTF-8
	 *
	 * @access public
	 * @param string $str input string
	 * @param string $encoding encoding of source string
	 * @return string converted UTF-8 string
	 */
	public static function encodeUtf8($str, $encoding = '', $onlyEncode = false) {
		if (extension_loaded('mbstring')) {
			// detect encoding
			if (empty($encoding)) {
				$encoding = mb_detect_encoding($str);
			}
			// convert to UTF-8
			$str = mb_convert_encoding($str, 'UTF-8', $encoding);
		} else {
			$str = utf8_encode($str);
		}
		$str = Xoonips_Utils::htmlNumericEntities($str);
		if (!$onlyEncode) {
			return mb_decode_numericentity($str, array(0x0, 0x10000, 0, 0xfffff), 'UTF-8');
		} else {
			return $str;
		}
	}

	/**
	 * decode utf8 string to other encoding with HTML numeric entities or url
	 * encoded string
	 *
	 * @access public
	 * @param string $str input utf8 string
	 * @param string $encoding output encoding
	 * @param string $fallback unmapped character encoding method
	 *   'h' : encode to HTML numeric entities
	 *   'u' : encode to UTF-8 based url string
	 * @return string converted string
	 */
	public static function decodeUtf8($str, $encoding, $fallback) {
		// convert to output encoding
		$map = array('SJIS-win' => 'CP932', 'EUC-JP' => 'CP932', 'ISO-8859-1' => 'CP1252', 'Windows-1252' => 'CP1252');
		if ($encoding == 'UTF-8') {
			$ret = $str;
		} else if($encoding == 'ASCII' && $fallback == 'u') {
			$ret = $str;
		} else if (isset($map[$encoding]) && $map[$encoding] != null) {
			$ret = self::utf8ToCharset($str, $map[$encoding], $fallback);
			if ($encoding == 'EUC-JP') {
				$tmp = $ret;
				$ret = @mb_convert_encoding($tmp, 'eucJP-win', 'SJIS-win');
				if ($ret === false) {
					$ret = @mb_convert_encoding($tmp, 'EUC-JP', 'Shift_JIS');
				}
			}
		} else {
			$ret = self::utf8ToCharset($str, 'US-ASCII', $fallback);
		}
		return $ret;
	}

	/**
	 * convert encoding from UTF-8 to each charset with HTML numeric entities
	 *
	 * @access private
	 * @param string $utf8 input UTF-8 string
	 * @param string $charset output encoding
	 * @param string $fallback unmapped character encoding method
	 *   'h' : encode to HTML numeric entities
	 *   'u' : encode to UTF-8 based url string
	 * @return string converted string
	 */
	private static function utf8ToCharset($utf8, $charset, $fallback) {
		static $unicode_map = array();
		if (!self::loadCharset($charset, $unicode_map)) {
			return '';
		}
		$len = strlen($utf8);
		$res = '';
		for ($i = 0; $i < $len; $i++) {
			if (ord($utf8[$i]) <= 191) {
				$ord = ord($utf8[$i]);
				$char = $utf8[$i];
			} elseif (192 <= ord($utf8[$i]) && ord($utf8[$i]) <= 223) {
				$ord = (((ord($utf8[$i]) - 192) << 6) + ord($utf8[$i+1]) - 128);
				$char = substr($utf8, $i, 2);
				$i++;
			} elseif (224 <= ord($utf8[$i]) && ord($utf8[$i]) <= 239) {
				$ord = (((ord($utf8[$i]) - 224) << 12) + ((ord($utf8[$i+1]) - 128) << 6) + ord($utf8[$i+2]) - 128);
				$char = substr($utf8, $i, 3);
				$i += 2;
			} else {
				$ord = (((ord($utf8[$i]) - 240) << 18) + ((ord($utf8[$i+1]) - 128) << 12) + ((ord($utf8[$i+2]) - 128) << 6) + ord($utf8[$i+3]) - 128);
				$char = substr($utf8, $i, 2);
				$i += 3;
			}

			if (isset($unicode_map[$charset][$ord])) {
				$num = $unicode_map[$charset][$ord];
				$res .= $num < 256 ? chr($num) : chr(intval($num / 256)) . chr($num % 256);
		    } elseif ($fallback == 'h') {
				$res .= '&#' . $ord . ';';
			} elseif ($fallback == 'u') {
				$res .= urlencode($char);
			}
		}
		return $res;
	}

	/**
	 * load character set mapping file
	 *
	 * @access private
	 * @param string $charset name of character set
	 * @return bool false if failure
	 */
	private static function loadCharset($charset, &$unicode_map) {
		if (isset($unicode_map[$charset])) {
			return true;
		}
		$trustDirname = self::getTrustDirname();
		$mapfile_path = XOOPS_TRUST_PATH . "/modules/$trustDirname/include/unicode/" . $charset . '.TXT';
		$lines = @file_get_contents($mapfile_path);
		if (empty($lines)) {
			error_log('Failed to read character set : ' . $charset);
			return false;
		}
		// omit comment line and empty line
		$lines = preg_replace("/\n\n/m", '', preg_replace('/#.*$/m', '', $lines));
		$lines = explode("\n", $lines);
		foreach ($lines as $line) {
			if (preg_match('/^0x([A-Fa-f0-9]{1,4})\\s+0x([A-Fa-f0-9]{1,4})\\s*$/', $line, $columns)) {
				$unicode_map[$charset][hexdec($columns[2])] = hexdec($columns[1]);
			}
		}
		return true;
	}

	/**
	 * convert text to numeric entities
	 *
	 * @access public
	 * @param string $text input string
	 * @return string converted string
	 */
	public static function htmlNumericEntities($text) {
		return str_replace(self::getCharRef(), self::getNumericRef(), $text);
	}

	private static function getCharRef() {
		return array(
			'&quot;',   '&amp;',	'&apos;',	 '&lt;',	   '&gt;',
			'&nbsp;',   '&iexcl;',	'&cent;',	 '&pound;',	   '&curren;',
			'&yen;',    '&brvbar;', '&sect;',	 '&uml;',	   '&copy;',
			'&ordf;',   '&laquo;',	'&not;',	 '&shy;',	   '&reg;',
			'&macr;',   '&deg;',	'&plusmn;',  '&sup2;',	   '&sup3;',
			'&acute;',  '&micro;',	'&para;',	 '&middot;',   '&cedil;',
			'&sup1;',   '&ordm;',	'&raquo;',	 '&frac14;',   '&frac12;',
			'&frac34;', '&iquest;', '&Agrave;',  '&Aacute;',   '&Acirc;',
			'&Atilde;', '&Auml;',	'&Aring;',	 '&AElig;',	   '&Ccedil;',
			'&Egrave;', '&Eacute;', '&Ecirc;',	 '&Euml;',	   '&Igrave;',
			'&Iacute;', '&Icirc;',	'&Iuml;',	 '&ETH;',	   '&Ntilde;',
			'&Ograve;', '&Oacute;', '&Ocirc;',	 '&Otilde;',   '&Ouml;',
			'&times;',	'&Oslash;', '&Ugrave;',  '&Uacute;',   '&Ucirc;',
			'&Uuml;',   '&Yacute;', '&THORN;',	 '&szlig;',	   '&agrave;',
			'&aacute;', '&acirc;',	'&atilde;',  '&auml;',	   '&aring;',
			'&aelig;',	'&ccedil;', '&egrave;',  '&eacute;',   '&ecirc;',
			'&euml;',   '&igrave;', '&iacute;',  '&icirc;',	   '&iuml;',
			'&eth;',    '&ntilde;', '&ograve;',  '&oacute;',   '&ocirc;',
			'&otilde;', '&ouml;',   '&divide;',  '&oslash;',   '&ugrave;',
			'&uacute;', '&ucirc;',	'&uuml;',	 '&yacute;',   '&thorn;',
			'&yuml;',   '&OElig;',	'&oelig;',	 '&Scaron;',   '&scaron;',
			'&Yuml;',   '&fnof;',   '&circ;',	 '&tilde;',	   '&Alpha;',
			'&Beta;',   '&Gamma;',	'&Delta;',	 '&Epsilon;',  '&Zeta;',
			'&Eta;',    '&Theta;',	'&Iota;',	 '&Kappa;',	   '&Lambda;',
			'&Mu;',	    '&Nu;',	    '&Xi;',	     '&Omicron;',  '&Pi;',
			'&Rho;',    '&Sigma;',	'&Tau;',	 '&Upsilon;',  '&Phi;',
			'&Chi;',    '&Psi;',    '&Omega;',	 '&alpha;',	   '&beta;',
			'&gamma;',	'&delta;',	'&epsilon;', '&zeta;',	   '&eta;',
			'&theta;',	'&iota;',   '&kappa;',	 '&lambda;',   '&mu;',
			'&nu;',	    '&xi;',	    '&omicron;', '&pi;',	   '&rho;',
			'&sigmaf;', '&sigma;',	'&tau;',	 '&upsilon;',  '&phi;',
			'&chi;',	'&psi;',    '&omega;',	 '&thetasym;', '&upsih;',
			'&piv;',	'&ensp;',   '&emsp;',	 '&thinsp;',   '&zwnj;',
			'&zwj;',	'&lrm;',    '&rlm;',	 '&ndash;',	   '&mdash;',
			'&lsquo;',	'&rsquo;',	'&sbquo;',	 '&ldquo;',	   '&rdquo;',
			'&bdquo;',	'&dagger;', '&Dagger;',  '&bull;',	   '&hellip;',
			'&permil;', '&prime;',	'&Prime;',	 '&lsaquo;',   '&rsaquo;',
			'&oline;',	'&frasl;',	'&euro;',	 '&image;',	   '&weierp;',
			'&real;',	'&trade;',	'&alefsym;', '&larr;',	   '&uarr;',
			'&rarr;',	'&darr;',   '&harr;',	 '&crarr;',	   '&lArr;',
			'&uArr;',	'&rArr;',   '&dArr;',	 '&hArr;',	   '&forall;',
			'&part;',	'&exist;',	'&empty;',	 '&nabla;',	   '&isin;',
			'&notin;',	'&ni;',	    '&prod;',	 '&sum;',	   '&minus;',
			'&lowast;', '&radic;',	'&prop;',	 '&infin;',	   '&ang;',
			'&and;',	'&or;',	    '&cap;',	 '&cup;',	   '&int;',
			'&there4;', '&sim;',    '&cong;',	 '&asymp;',	   '&ne;',
			'&equiv;',	'&le;',	    '&ge;',	     '&sub;',	   '&sup;',
			'&nsub;',	'&sube;',   '&supe;',	 '&oplus;',	   '&otimes;',
			'&perp;',	'&sdot;',   '&lceil;',	 '&rceil;',	   '&lfloor;',
			'&rfloor;', '&lang;',   '&rang;',	 '&loz;',	   '&spades;',
			'&clubs;',	'&hearts;', '&diams;'
		);
	}

	private static function getNumericRef() {
		return array(
			'&#34;',   '&#38;',   '&#39;',   '&#60;',   '&#62;',
			'&#160;',  '&#161;',  '&#162;',  '&#163;',  '&#164;',
			'&#165;',  '&#166;',  '&#167;',  '&#168;',  '&#169;',
			'&#170;',  '&#171;',  '&#172;',  '&#173;',  '&#174;',
			'&#175;',  '&#176;',  '&#177;',  '&#178;',  '&#179;',
			'&#180;',  '&#181;',  '&#182;',  '&#183;',  '&#184;',
			'&#185;',  '&#186;',  '&#187;',  '&#188;',  '&#189;',
			'&#190;',  '&#191;',  '&#192;',  '&#193;',  '&#194;',
			'&#195;',  '&#196;',  '&#197;',  '&#198;',  '&#199;',
			'&#200;',  '&#201;',  '&#202;',  '&#203;',  '&#204;',
			'&#205;',  '&#206;',  '&#207;',  '&#208;',  '&#209;',
			'&#210;',  '&#211;',  '&#212;',  '&#213;',  '&#214;',
			'&#215;',  '&#216;',  '&#217;',  '&#218;',  '&#219;',
			'&#220;',  '&#221;',  '&#222;',  '&#223;',  '&#224;',
			'&#225;',  '&#226;',  '&#227;',  '&#228;',  '&#229;',
			'&#230;',  '&#231;',  '&#232;',  '&#233;',  '&#234;',
			'&#235;',  '&#236;',  '&#237;',  '&#238;',  '&#239;',
			'&#240;',  '&#241;',  '&#242;',  '&#243;',  '&#244;',
			'&#245;',  '&#246;',  '&#247;',  '&#248;',  '&#249;',
			'&#250;',  '&#251;',  '&#252;',  '&#253;',  '&#254;',
			'&#255;',  '&#338;',  '&#339;',  '&#352;',  '&#353;',
			'&#376;',  '&#402;',  '&#710;',  '&#732;',  '&#913;',
			'&#914;',  '&#915;',  '&#916;',  '&#917;',  '&#918;',
			'&#919;',  '&#920;',  '&#921;',  '&#922;',  '&#923;',
			'&#924;',  '&#925;',  '&#926;',  '&#927;',  '&#928;',
			'&#929;',  '&#931;',  '&#932;',  '&#933;',  '&#934;',
			'&#935;',  '&#936;',  '&#937;',  '&#945;',  '&#946;',
			'&#947;',  '&#948;',  '&#949;',  '&#950;',  '&#951;',
			'&#952;',  '&#953;',  '&#954;',  '&#955;',  '&#956;',
			'&#957;',  '&#958;',  '&#959;',  '&#960;',  '&#961;',
			'&#962;',  '&#963;',  '&#964;',  '&#965;',  '&#966;',
			'&#967;',  '&#968;',  '&#969;',  '&#977;',  '&#978;',
			'&#982;',  '&#8194;', '&#8195;', '&#8201;', '&#8204;',
			'&#8205;', '&#8206;', '&#8207;', '&#8211;', '&#8212;',
			'&#8216;', '&#8217;', '&#8218;', '&#8220;', '&#8221;',
			'&#8222;', '&#8224;', '&#8225;', '&#8226;', '&#8230;',
			'&#8240;', '&#8242;', '&#8243;', '&#8249;', '&#8250;',
			'&#8254;', '&#8260;', '&#8364;', '&#8465;', '&#8472;',
			'&#8476;', '&#8482;', '&#8501;', '&#8592;', '&#8593;',
			'&#8594;', '&#8595;', '&#8596;', '&#8629;', '&#8656;',
			'&#8657;', '&#8658;', '&#8659;', '&#8660;', '&#8704;',
			'&#8706;', '&#8707;', '&#8709;', '&#8711;', '&#8712;',
			'&#8713;', '&#8715;', '&#8719;', '&#8721;', '&#8722;',
			'&#8727;', '&#8730;', '&#8733;', '&#8734;', '&#8736;',
			'&#8743;', '&#8744;', '&#8745;', '&#8746;', '&#8747;',
			'&#8756;', '&#8764;', '&#8773;', '&#8776;', '&#8800;',
			'&#8801;', '&#8804;', '&#8805;', '&#8834;', '&#8835;',
			'&#8836;', '&#8838;', '&#8839;', '&#8853;', '&#8855;',
			'&#8869;', '&#8901;', '&#8968;', '&#8969;', '&#8970;',
			'&#8971;', '&#9001;', '&#9002;', '&#9674;', '&#9824;',
			'&#9827;', '&#9829;', '&#9830;'
		);
	}

	public static function getCodeToLatin1($from, $to) {
		$chars = array();
		for ($i = $from; $i <= $to; $i++) {
			$chars[] = chr($i);
		}
		return mb_convert_encoding(implode('', $chars), 'UTF-8', 'ISO-8859-1');
	}

	public static function getCodeToUtf8($code_set) {
		$chars = array();
		foreach ($code_set as $code) {
			if (count($code) == 2) {
				$chars[] = pack('C*', $code[0], $code[1]);
			} else if (count($code) == 3) {
				$chars[] = pack('C*', $code[0], $code[1], $code[2]);
			} else if (count($code) == 4) {
				$chars[] = pack('C*', $code[0], $code[1], $code[2], $code[3]);
			}
		}
		return implode('', $chars);
	}

	public static function loadMessage($dirname) {
		self::loadLanguage($dirname, 'main');
	}

	public static function loadModinfoMessage($dirname) {
		self::loadLanguage($dirname, 'modinfo');
	}

	public static function loadAdminMessage($dirname) {
		self::loadLanguage($dirname, 'admin');
	}

	public static function loadBlocksMessage($dirname) {
		self::loadLanguage($dirname, 'blocks');
	}

	public static function loadLanguage($dirname, $name) {
		$root =& XCube_Root::getSingleton();
		$mLanguageName = $root->mLanguageManager->getLocale();
		$fileName = XOOPS_MODULE_PATH . '/' . $dirname . '/language/' . $mLanguageName . '/' . $name . '.php';
		if (!self::loadFile($fileName)) {
			$fileName = XOOPS_TRUST_PATH . '/modules/' . $dirname . '/language/' . $mLanguageName . '/' . $name . '.php';
			if(!self::loadFile($fileName)) {
				$fileName = XOOPS_TRUST_PATH . '/modules/' . $dirname . '/language/english/' . $name . '.php';
				self::loadFile($fileName);
			}
		}
	}

	private static function loadFile($filename) {
		if (file_exists($filename)) {
			global $xoopsDB, $xoopsTpl, $xoopsRequestUri, $xoopsModule, $xoopsModuleConfig,
				   $xoopsModuleUpdate, $xoopsUser, $xoopsUserIsAdmin, $xoopsTheme,
				   $xoopsConfig, $xoopsOption, $xoopsCachedTemplate, $xoopsLogger, $xoopsDebugger;

			require_once $filename;
			return true;
		}

		return false;
	}

	/**
	 * get mail_template directory name on current language
	 *
	 * @access public
	 * @param string $dirname module directory name
	 * @param string $trustDirname module trust directory name
	 * @return string accessible mail_template directory name
	 */
	public static function mailTemplateDir($dirname = null, $trustDirname = null) {
		if (is_null($dirname)) {
			$dirname = 'xoonips';
		}
		$resource = 'mail_template/';
		$basepath = empty($trustDirname) ? XOOPS_ROOT_PATH : XOOPS_TRUST_PATH;
		$dirname = empty($trustDirname) ? $dirname : $trustDirname;
		$root =& XCube_Root::getSingleton();
		$lang = $root->mLanguageManager->getLanguage();
		$langpath = $basepath . '/modules/' . $dirname . '/language/' .$lang . '/' . $resource;
	 	return $langpath;
	}

	public static function ccTemplateDir($trustDirname = null) {
		if (is_null($trustDirname)) {
			$trustDirname = XOONIPS_TRUST_DIRNAME;
		}
		$resource = 'cc/';
		$root =& XCube_Root::getSingleton();
		$lang = $root->mLanguageManager->getLanguage();
		$langpath = XOOPS_TRUST_PATH . '/modules/' . $trustDirname. '/language/' . $lang . '/' . $resource;
		return $langpath;
	}

	public static function fontPath($fontname) {
		$langpath = XOOPS_TRUST_PATH . '/modules/' . XOONIPS_TRUST_DIRNAME . '/language/' ._MD_XOONIPS_FONT_LANGUAGE . '/' . $fontname;
		return $langpath;
	}

	public static function readPagetype($pagetype, $read_once = true) {
  		$root =& XCube_Root::getSingleton();
  		$root->mLanguageManager->loadPageTypeMessageCatalog($pagetype);
	}

	public static function getDirname() {
		Global $xoopsModule;
		return strtolower($xoopsModule->getVar('dirname'));
	}

	public static function getTrustDirname() {
        Global $xoopsModule;
        return $xoopsModule->getVar('trust_dirname');
    }

    public static function allBufferClear() {
		$handlers = ob_list_handlers();
		while (!empty($handlers)) {
			ob_end_clean();
			$handlers = ob_list_handlers();
		}
	}

	public static function convertList($value) {
		$modules = explode(',', $value);
		$list = array();
		foreach ($modules as $module) {
			$limit = explode(':', $module);
			$list[$limit[0]] = $limit[1];
		}
		return $list;
	}
}

