<?php
/**
 * 絵文字変換処理クラス
 *
 * 各キャリアの文字列を相互に変換するクラスです。
 *
 **/
// 2004-01-16 [追加] 「iモード拡張絵文字」の変換処理
// 2004-01-19 [追加] 配列で渡せるように拡張
// 2004-06-25 [修正] 配列渡しで inType,outTypeも渡すように修正
// 2005-03-03 [追加] User-Agentに「Vodafone」がある場合の処理を追加

class Emoji {
	/**
	 * エラー
	 */
	var $err = '';
	var $typeSelf;
	var $emoji_image_dir = '/emoji/';		// 絵文字のPC用gif画像が格納されているURL
	var $noEmoji = '＝';					// 対応する絵文字が無い場合に表示する文字
	var $currentDir;

	var $iTable;
	var $eTable;
	var $jTable;
	var $ixTable;

	function Emoji() {
		$this->currentDir = dirname(__FILE__);
	}

	function getEmojiImageDir() {
		return $this->emoji_image_dir;
	}

	function getTypeSelf() {

		if($this->typeSelf == '') {
			$ua = explode('/', $_SERVER['HTTP_USER_AGENT']);
			switch($ua[0]) {
			case 'DoCoMo':		// i-mode 用の処理
				$this->typeSelf = 'i';
				break;
			case 'J-PHONE':		// J-SKY 用の処理
			case 'Vodafone':	// Vodafone 用の処理
			case 'SoftBank':	// SoftBank 用の処理
				$this->typeSelf = 'j';
				break;
			case 'UP.Browser':	// au 旧端末用の処理
				$this->typeSelf = 'e';
				break;
			default:
				if(substr($ua[0], 0, 4) == 'KDDI') {	// au WAP2.0 対応端末用の処理
					$this->typeSelf = 'e';
				} else {	// それ以外(PCなど)
					$this->typeSelf = 'p';
				}
			}
		}
		return $this->typeSelf;
	}

	function prepareTable($type) {
		switch($type) {
		case 'i':
		case 'e':
		case 'j':
		case 'ix':
			if(!isset($this->{$type . 'Table'})) {
//				require_once($this->currentDir . '/emoji.'.$type.'.dat');
				require($this->currentDir . '/emoji.'.$type.'.dat');
				$this->{$type . 'Table'} = &${$type . 'Table'};
			}
		}
	}

	function convEmojiFromI($str, $outType) {
		if(!preg_match("/[\xF8\xF9]|&#63[0-9]{3};|&#x[0-f]{4};/", $str))	//	imode絵文字含まれない
			return $str;

		static $set, $match_bin, $match_dec;
		switch($outType) {
		case $set:
			break;
		case 'rm':
			$this->prepareTable('i');
			foreach($this->iTable as $key => $val) {
				$match_bin[$val['i']] = '';
				$match_dec[$val['i1']] = '';
			}
			$this->prepareTable('ix');
			foreach($this->ixTable as $key => $val) {
				$match_bin[$val['i']] = '';
				$match_dec[$val['i1']] = '';
			}
			break;
		case 'i':
			$this->prepareTable('i');
			foreach($this->iTable as $key => $val) 
				$match_dec[$val['i1']] = $val['i'];
			break;
		case 'j':
		case 'e':
			$this->prepareTable($outType);
			$outTable = $this->{$outType . 'Table'};
			$this->prepareTable('i');
			foreach($this->iTable as $key => $val) {
				$new_val = isset($outTable[$val[$outType]][$outType]) ? $outTable[$val[$outType]][$outType] : $this->noEmoji;
				$match_bin[$val['i']] = $new_val;
				$match_dec[$val['i1']] = $new_val;
			}
			$this->prepareTable('ix');
			foreach($this->ixTable as $key => $val) {
				$new_val = isset($outTable[$val[$outType]][$outType]) ? $outTable[$val[$outType]][$outType] : $this->noEmoji;
				$match_bin[$val['i']] = $new_val;
				$match_dec[$val['i1']] = $new_val;
			}
			break;
		case 'p':
			$this->prepareTable('i');
			foreach($this->iTable as $key => $val) {
				$new_val = '<img src="' . $this->emoji_image_dir . $key . '.gif" border="0">';
				$match_bin[$val['i']] = $new_val;
				$match_dec[$val['i1']] = $new_val;
			}
			$this->prepareTable('ix');
			foreach($this->ixTable as $key => $val) {
				$new_val = '<img src="' . $this->emoji_image_dir . 'ex' . $key . '.gif" border="0">';
				$match_bin[$val['i']] = $new_val;
				$match_dec[$val['i1']] = $new_val;
			}
			break;
		}
		$set = $outType;

		if($outType != 'i') {	// i → i 変換でなければ、絵文字バイナリ変換する
			$ret = '';
			for($i = 0; $i < strlen($str); $i++) {
				$chr = substr($str, $i, 2);	//2バイト分
				if(preg_match("/^[\xF8\xF9]./", $chr) && isset($match_bin[$chr])) {// i-mode絵文字バイナリ
					$ret .= $match_bin[$chr];
					$i++;
//				} elseif(preg_match("/^\x90-\x9F\xE0-\xF7\xF9-\xFC]./", $chr)) {	// 絵文字以外の2バイト
				} elseif(preg_match("/^[\x81-\x9F\xE0-\xFC][\x40-\x7E\x80-\xFC]/", $chr)) {	// 絵文字以外の2バイト
					$ret .= $chr;
					$i++;
				} else {
					$ret .= substr($str, $i, 1);	// 1バイト文字
				}
			}
		} else {

			$ret = $str;
		}

		return str_replace(array_keys($match_dec), array_values($match_dec), $ret);
	}

	function convEmojiFromJ($str, $outType) {
		if($outType == 'j' || !preg_match('/\x1B\$.*\x0F/', $str))	// J→J変換、またはJ-SKY絵文字含まれない
			return $str;

		while(preg_match('/^(.*)(\x1B\$([^\x0F])([^\x0F]{2,})\x0F)(.*)$/s', $str, $match)) {
			$emojis = '';
			for($i = 0; $i < strlen($match[4]); $i++)
				$emojis .= "\x1B\$" . $match[3] . substr($match[4], $i, 1) . "\x0F";
			$str = $match[1] . $emojis . $match[5];
		}

		static $set, $match_bin, $match_dec;
		switch($outType) {
		case $set:
			break;
		case 'rm':
			$this->prepareTable('j');
			foreach($this->jTable as $key => $val) 
				$match_bin[$val['j']] = '';
			break;
		case 'i':
		case 'e':
			$this->prepareTable($outType);
			$outTable = $this->{$outType . 'Table'};
			$this->prepareTable('j');
			foreach($this->jTable as $key => $val) 
				$match_bin[$val['j']] = isset($outTable[$val[$outType]][$outType]) ? $outTable[$val[$outType]][$outType] : $this->noEmoji;
			break;
		case 'p':
			$this->prepareTable('j');
			foreach($this->jTable as $key => $val) 
				$match_bin[$val['j']] = isset($val['i']) ? '<img src="' . $this->emoji_image_dir . $val['i'] . '.gif" border="0">' : $this->noEmoji;
			break;
		}
		$set = $outType;

		return str_replace(array_keys($match_bin), array_values($match_bin), $str);
	}

	function convEmojiFromE($str, $outType) {
		if($outType == 'e' || !preg_match("/[\xF6\xF7]|<img\s+localsrc=[\"|'](\d+)[\"|'].*?>|<IMG\s+ICON=[\"|'](\d+)[\"|'].*?>/is", $str))	// E→E変換、またはezweb絵文字含まれない
			return $str;

		static $set, $match_bin, $match_dec;
		switch($outType) {
		case $set:
			break;
		case 'rm':
			$this->prepareTable('e');
			foreach($this->eTable as $key => $val) {
				$match_bin[$val['e']] = '';
				$match_dec[$val['e1']] = '';
			}
			break;
		case 'i':
		case 'j':
			$this->prepareTable($outType);
			$outTable = $this->{$outType . 'Table'};
			$this->prepareTable('e');
			foreach($this->eTable as $key => $val) {
				$new_val = isset($outTable[$val[$outType]][$outType]) ? $outTable[$val[$outType]][$outType] : $this->noEmoji;
				$match_bin[$val['e']] = $new_val;
				$match_dec[$val['e1']] = $new_val;
			}
			break;
		case 'p':
			$this->prepareTable('e');
			foreach($this->eTable as $key => $val) {
				$new_val = isset($val['i']) ? '<img src="' . $this->emoji_image_dir . $val['i'] . '.gif" border="0">' : $this->noEmoji;
				$match_bin[$val['e']] = $new_val;
				$match_dec[$val['e1']] = $new_val;
			}
			break;
		}
		$set = $outType;

		$ret = '';
//		if($outType != 'e') {	// e → e 変換でなければ、絵文字バイナリ変換する
			for($i = 0; $i < strlen($str); $i++) {
				$chr = substr($str, $i, 2);	//2バイト分
				if(preg_match("/^[\xF6\xF7]./", $chr) && isset($match_bin[$chr])) {// ezweb絵文字バイナリ
					$ret .= $match_bin[$chr];
					$i++;
//				} elseif(preg_match("/^\x90-\x9F\xE0-\xF7\xF9-\xFC]./", $chr)) {	// 絵文字以外の2バイト
				} elseif(preg_match("/^[\x81-\x9F\xE0-\xFC][\x40-\x7E\x80-\xFC]/", $chr)) {	// 絵文字以外の2バイト
					$ret .= $chr;
					$i++;
				} else {
					$ret .= substr($str, $i, 1);	// 1バイト文字
				}
			}
//		}

		return preg_replace(array('/<img\s+localsrc=["|\'](\d+)["|\'].*?>/is', '/<IMG\s+ICON=["|\'](\d+)["|\'].*?>/is'), $match_dec['\\1'], $ret);
	}

	// 絵文字変換関数
	function convEmoji($str, $outType = null, $inType = null) {
// 2004-01-15 [追加]ここから
		if(is_array($str)) {
			foreach ($str as $key => $val)
				$str[$key] = $this->convEmoji($val, $outType, $inType);
			return $str;
		} else {
// 2004-01-15 [追加]ここまで
			if(strlen($str) == 0) 
				return $str;

			switch($outType) {
			case 'rm':
			case 'i':
			case 'j':
			case 'e':
			case 'p':
				break;
			default:
				$outType = $this->getTypeSelf();
			}

			switch($inType) {
			case 'i':
				return $this->convEmojiFromI($str, $outType);
			case 'j':
				return $this->convEmojiFromJ($str, $outType);
			case 'e':
				return $this->convEmojiFromE($str, $outType);
			default:
				$str = $this->convEmojiFromE($str, $outType);
				$str = $this->convEmojiFromJ($str, $outType);
				$str = $this->convEmojiFromI($str, $outType);
				return $str;
			}
		}
	}


	var $inputTable = array(
		'1' => 'hiragana',
		'2' => 'katakana',
		'3' => 'alphabet',
		'4' => 'numeric'
	);

	function convInputToI($str) {

		$in = $str;
		while(preg_match('/^(.*?)(<(input|teaxtarea)\s+(.*?)>)(.*)$/is', $in, $match)) {
			$changed = false;
			if(preg_match('/^(.*?)(mode(\s*=\s*["|\']?)(\d)(["|\']?))(.*)$/is', $match[2], $match_in) && ($key = array_search($match_in[4], $this->inputTable)) !== false) {
				$match[2] = $match_in[1] . 'istyle' . $match_in[3] . $key . $match_in[5] . $match_in[6];
				$changed = true;
			}
			if(preg_match('/^(.*?)(directkey(\s*=\s*["|\']?\d["|\']?))(.*)$/is', $match[2], $match_in)) {
				$match[2] = $match_in[1] . 'accesskey' . $match_in[3] . $match_in[4];
				$changed = true;
			}
			$out .= $match[1] . $match[2];
			$in = $match[5];
		}
		return $out . $in;
	}

	function convInputToJ($str) {

		$in = $str;
		while(preg_match('/^(.*?)(<(input|teaxtarea)\s+(.*?)>)(.*)$/is', $in, $match)) {
			$changed = false;
			if(preg_match('/^(.*?)(istyle\s*=\s*(["|\']?)(\d)(["|\']?))(.*)$/is', $match[2], $match_in) && isset($this->inputTable[$match_in[4]])) {
				$match[2] = $match_in[1] . 'mode=' . $match_in[3] . $this->inputTable[$match_in[4]] . $match_in[5] . $match_in[6];
				$changed = true;
			}
			if(preg_match('/^(.*?)(accesskey\s*=\s*(["|\']?\d["|\']?))(.*)$/is', $match[2], $match_in)) {
				$match[2] = $match_in[1] . 'directkey=' . $match_in[3] . $match_in[4];
				$changed = true;
			}
			$out .= $match[1] . $match[2];
			$in = $match[5];
		}
		return $out . $in;
	}

	// 入力モード、アクセスキー変換関数
	function convInput($str, $outType = null, $inType = null) {

		if(strlen($str) == 0 || !preg_match('/<(input|teaxtarea)\s+.*?>/is', $str))	//	inputタグ含まれない
			return $str;

		if($outType == null)
			$outType = $this->getTypeSelf();

		switch($outType) {
		case 'i':
		case 'e':
			return $this->convInputToI($str, $outType);
		case 'j':
			return $this->convInputToJ($str, $outType);
		default:
			return $str;
		}

	}

}
?>
