<?php
  /**************************************************************************\
  * phpGroupWare API - CharSet code convert class                            *
  * (C) Copyright 2001 Yoshihiro Kamimura your@itheart.com                   *
  * ------------------------------------------------------------------------ *
  * This is not part of phpGroupWare, but is used by phpGroupWare.           * 
  * http://www.phpgroupware.org/                                             * 
  * ------------------------------------------------------------------------ *
  * This program is free software; you can redistribute it and/or modify it  *
  * under the terms of the GNU Lesser General Public License as published    *
  * by the Free Software Foundation; either version 2.1 of the License, or   *
  * any later version.                                                       *
  \**************************************************************************/

	/* $Id: class.codecv_ja.inc.php,v 1.1.10.3 2004/12/01 09:29:09 kazuyan Exp $ */

class codecv {

	var $m_inside;
	var $m_outside;
	var $m_needconv;
	var $func_name;
	var $lang;
		
	function codecv() {
		$this->m_inside = strtolower(lang('charset'));
		$this->m_outside = strtolower(lang('outcharset'));
		$this->m_needconv = ($this->m_inside != $this->m_outside);
		$this->lang = 'ja';
		if (extension_loaded('mbstring'))
		{
			$this->func_name = array(
				//'get_charcode'		=> 'get_charcode_mbstring',
				'get_charcode'		=> 'get_charcode_jcode',
				'jistoeuc'			=> 'jistoeuc_mbstring',
				'euctojis'			=> 'euctojis_mbstring',
				'euctosjis'			=> 'euctosjis_mbstring',
				'sjistoeuc'			=> 'sjistoeuc_mbstring',
				'utf8toeuc'			=> 'utf8toeuc_mbstring',
				'euctoutf8'			=> 'euctoutf8_mbstring',
				'utf7_imaptoeuc'	=> 'utf7_imaptoeuc_mbstring',
				'euctoimap_utf7'	=> 'euctoimap_utf7_mbstring'
			);	
		}
		else 
		{
			$this->func_name = array(
				'get_charcode'		=> 'get_charcode_jcode',
				'jistoeuc'			=> 'jistoeuc_jcode',
				'euctojis'			=> 'euctojis_jcode',
				'euctosjis'			=> 'euctosjis_jcode',
				'sjistoeuc'			=> 'sjistoeuc_jcode',
				'utf8toeuc'			=> 'utf8toeuc_jcode',
				'euctoutf8'			=> 'euctoutf8_jcode',
				'utf7_imaptoeuc'	=> 'utf7_imaptoeuc_jcode',
				'euctoimap_utf7'	=> 'euctoimap_utf7_jcode'				
			);	
		}
	}
	
	function get_charcode_mbstring($str)
	{
		$result = strtoupper(mb_detect_encoding($str, array('ASCII','JIS','ISO-2022-JP','EUC-JP','SJIS','UTF-8')));
		if ($result == 'EUC-JP')
		  	$result = 'EUC';
		elseif ($result == 'ASCII')
			$result = 'US-ASCII';
		elseif ($result == 'ISO-2022-JP')
			$result = 'JIS';
		elseif ($result == 'UTF-8')
			$result = 'UTF8';
		elseif (!$result)
			$result = 'UNKNOWN';
		return $result;	
	}
	
	function get_charcode_jcode($str)
	{
		$is_utf8  = TRUE;
		$is_ascii = TRUE;
		
		for ($i = 0; $i < strlen($str); $i++) {
			$b = unpack("C*", substr($str, $i, 3));
			if ($i == 0 && $b[1] == 0xEF && $b[2] == 0xBB && $b[3] == 0xBF)
				return 'UTF8';						//BOM of UTF-8
			if ($b[1] == 0x1B && $b[2] == 0x24)
				return 'JIS';						//Escape Sequence of JIS
			if ($b[1] < 0x80) continue;  			//US-ASCII
			$is_ascii = FALSE;
			if (0x80 < $b[1] && $b[1] < 0xA0)
				return 'SJIS';
			if (0xA0 < $b[1] && $b[1] < 0xC0)
				return 'EUC';
			if ($b[1] > 0xEF)
				return 'EUC';
			if ($b[2] < 0x80)
				return 'SJIS';
			if ($b[2] > 0xFC)
				return 'EUC';
			if ($is_utf8) {
				if (0xDF < $b[1] && $b[1] < 0xF0) {
					if ((0x7F < $b[2] && $b[2] < 0xC0) && (0x7F < $b[3] && $b[3] < 0xC0))
						return 'UTF8';
					else 
						$is_utf8 = FALSE;
				}
				elseif (!(0x7F < $b[2] && $b[2] < 0xC0)) {
					return 'EUC';
				}
			}
			elseif (0xBF < $b[1] && $b[1] < 0xE0) {
				return 'EUC';
			}
			$i++;
		}
		if ($is_ascii)
			return 'US-ASCII';
		return 'UNKNOWN';	
	}
	
	function get_charcode($str) {
		$func_name = $this->func_name['get_charcode'];
		return $this->$func_name($str);	
	}
	
	function jistoeuc_mbstring($str_jis)
	{
		return mb_convert_encoding($str_jis, 'EUC-JP', 'ISO-2022-JP');
	}
	
	function jistoeuc_jcode($str_jis)
	{
		$str_euc = '';
		$mode = 0;
		$b = unpack('C*', $str_jis);
		$n = count($b);

		for ($i = 1; $i <= $n; $i++) {
			while ($b[$i] == 0x1B) {
				if (($b[$i+1] == 0x24 && $b[$i+2] == 0x42)
					|| ($b[$i+1] == 0x24 && $b[$i+2] == 0x40)) {
					$mode = 1;
				} elseif (($b[$i+1] == 0x28 && $b[$i+2] == 0x49)) {
					$mode = 2;
				} else {
					$mode = 0;
				}
				$i += 3;
				if (!isset($b[$i])) break 2;
			}
			//Do convert
			if ($mode == 1) {
				$str_euc .= chr($b[$i] + 0x80).chr($b[++$i] + 0x80);
			} elseif ($mode == 2) {
				$str_euc .= chr(0x8E).chr($b[$i] + 0x80);
			} else {
				$str_euc .= chr($b[$i]);
			}
			/*
			if ($b[$i] == 0x1B) {
				if (($b[$i+1] == 0x24 && $b[$i+2] == 0x42) ||
			   	($b[$i+1] == 0x24 && $b[$i+2] == 0x40)) {
					$mode = 1;
				} elseif (($b[$i+1] == 0x28 && $b[$i+2] == 0x49)){
					$mode = 2;
				} else {
					$mode = 0;
				}
				$i += 3;
			}

			if ($mode == 1) {
				$b[$i] |= 0x80; $b[$i+1] |= 0x80;
				$str_euc .= pack('CC', $b[$i], $b[$i+1]);
				$i++;
			} elseif ($mode == 2) {
				$b[$i] |= 0x80;
				$str_euc .= pack('CC', 0x8E, $b[$i]);
			} else {
				$str_euc .= pack('C', $b[$i]);
			}
			*/
		}
		return $str_euc;		
	}

	function jistoeuc($str_jis) {
		if ($this->get_charcode($str_jis) != 'EUC')
		{
			$func_name = $this->func_name['jistoeuc'];
			return $this->$func_name($str_jis);
		}
		else 
			return $str_jis;
	}

	function euctojis_mbstring($str_euc)
	{
		return mb_convert_encoding($str_euc, 'ISO-2022-JP', 'EUC-JP');		
	}
	
	function euctojis_jcode($str_euc)
	{
		$str_jis = '';
		$mode = 0;
		$b = unpack('C*', $str_euc);
		$n = count($b);

		for ($i = 1; $i <= $n; $i++) {
			if ($b[$i] == 0x8E) {
				if ($mode != 2) {
					$mode = 2;
					$str_jis .= pack('CCC', 0x1B, 0x28, 0x49);
				}
				$b[$i+1] &= ~0x80;
				$str_JIS .= pack('C', $b[$i+1]);
				$i++;
			} elseif ($b[$i] > 0x8E) {
				if ($mode != 1) {
					$mode = 1;
					$str_jis .= pack('CCC', 0x1B, 0x24, 0x42);
				}
				$b[$i] &= ~0x80; $b[$i+1] &= ~0x80;
				$str_jis .= pack('CC', $b[$i], $b[$i+1]);
				$i++;
			} else {
				if ($mode != 0) {
					$mode = 0;
					$str_jis .= pack('CCC', 0x1B, 0x28, 0x42);
				}
				$str_jis .= pack("C", $b[$i]);
			}
		}

		if ($mode != 0)
		{
			$str_jis .= pack('CCC', 0x1B, 0x28, 0x42);
		}

		return $str_jis;		
	}
	
	function euctojis($str_euc) {
		if ($this->get_charcode($str_euc) != 'JIS')
		{
			$func_name = $this->func_name['euctojis'];
			return $this->$func_name($str_euc);
		}
		else 
			return $str_euc;
	}

	function in2out($str) {
		if ($this->m_needconv)
		{
			return	$this->euctojis($str);
		}
		else
		{
			return	$str;
		}
	}

	function out2in($str) {
		if ($this->m_needconv)
		{
			return	$this->jistoeuc($str);
		}
		else
		{
			return	$str;
		}
	}
	
	function euctosjis_mbstring($str_euc)
	{
		return mb_convert_encoding($str_euc, 'SJIS', 'EUC-JP');
	}
	
	function euctosjis_jcode($str_euc)
	{
        $str_sjis = '';
        $b = unpack("C*", $str_euc);
        $n = count($b);

        for ($i = 1; $i <= $n; $i++)
        {
            if ($b[$i] == 0x8E)
            {
                $str_sjis .= pack("C", $b[$i+1]);
                $i++;
            }
            elseif ($b[$i] >= 0x80)
            {
                if ($b[$i] & 0x01)
                {
                    $b[$i] >>= 1;
                    if ($b[$i] < 0x6F) $b[$i] += 0x31; else $b[$i] += 0x71;
                    if ($b[$i+1] > 0xDF) $b[$i+1] -= 0x60; else $b[$i+1] -= 0x61;
                }
                else
                {
				    $b[$i] >>= 1;
				    if ($b[$i] <= 0x6F) $b[$i] += 0x30; else $b[$i] += 0x70;
				    $b[$i+1] -= 0x02;
                }
                $str_sjis .= pack("CC", $b[$i], $b[$i+1]);
                $i++;
            }
            else
            {
                $str_sjis .= pack("C", $b[$i]);
            }
        }
        return $str_sjis;		
	}
	
    function euctosjis($str_euc)
    {
		if ($this->get_charcode($str_euc) != 'SJIS')
		{
 			$func_name = $this->func_name['euctosjis'];
			return $this->$func_name($str_euc);
		}
		else 
			return $str_euc;
    }

    function sjistoeuc_mbstring($str_sjis)
    {
		return mb_convert_encoding($str_sjis, 'EUC-JP', 'SJIS'); 	
    }
    
    function sjistoeuc_jcode($str_sjis)
    {
		$str_euc = '';
		$b = unpack("C*", $str_sjis);
		$n = count($b);
	
		for ($i = 1; $i <= $n; $i++) {
			if (0xA1 <= $b[$i] && $b[$i] <= 0xDF) {
				$str_euc .= pack("CC", 0x8E, $b[$i]);
			} elseif ($b[$i] >= 0x81) {
				$b[$i] <<= 1;
				if ($b[$i+1] < 0x9F) {
					if ($b[$i] < 0x13F) $b[$i] -= 0x61; else $b[$i] -= 0xE1;
					if ($b[$i+1] > 0x7E) $b[$i+1] += 0x60; else $b[$i+1] += 0x61;
				} else {
					if ($b[$i] < 0x13F) $b[$i] -= 0x60; else $b[$i] -= 0xE0;
					$b[$i+1] += 0x02;
				}
				$str_euc .= pack("CC", $b[$i], $b[$i+1]);
				$i++;
			} else {
				$str_euc .= pack("C", $b[$i]);
			}
		}
		return $str_euc;    	
    }    
       
	function sjistoeuc($str_sjis)
	{
		if ($this->get_charcode($str_sjis) != 'EUC')
		{
 			$func_name = $this->func_name['sjistoeuc'];
			return $this->$func_name($str_sjis);
		}
		else 
			return $str_sjis;
	}
	
	function auto2euc($str)
	{
		$from_charcode = $this->get_charcode($str);
		if ($from_charcode == 'SJIS')
			$str = $this->sjistoeuc($str);
		elseif ($from_charcode == 'JIS')
			$str = $this->jistoeuc($str);
		elseif ($from_charcode == 'UTF8')
			$str = $this->utf8toeuc($str);
		return $str;
	}
	
	function utf8toeuc_mbstring($str_utf8)
	{
		return mb_convert_encoding($str_utf8, 'EUC-JP', 'UTF-8');
	}
	
	function utf8toeuc_jcode($str_utf8)
	{
		return utf8_decode($str_utf8);
	}
		
	function utf8toeuc($str_utf8)
	{
		if ($this->get_charcode($str_utf8) != 'EUC')
		{
 			$func_name = $this->func_name['utf8toeuc'];
			return $this->$func_name($str_utf8);
		}
		else 
			return $str_utf8;
	}

	function euctoutf8_mbstring($str_euc)
	{
		return mb_convert_encoding($str_euc, 'UTF-8', 'EUC-JP');	
	}
	
	function euctoutf8_jcode($str_euc)
	{
		return utf8_encode($str_euc);
	}
	
	function euctoutf8($str_euc)
	{
		if ($this->get_charcode($str_euc) != 'UTF8')
		{
 			$func_name = $this->func_name['euctoutf8'];
			return $this->$func_name($str_euc);
		}
		else 
			return $str_euc;
	}
	
	function mb_chunk_split($str, $chunklen = 76, $end = "\r\n")
	{
		if ($this->get_charcode($str) == 'US-ASCII')
		{
			return chunk_split($str, $chunklen, $end);
		}
		for ($i = 0,$j = 0,$idx = 0;$i < strlen($str);)
		{
			$c = substr($str, $i, 1);
			$code = $this->get_charcode($c);
			if ($code == 'US-ASCII')
				$new_str[$idx] .= $c;
			else 
			{
				$c = substr($str, $i, 2);
				$code = $this->get_charcode($c);
				if ($code != 'US-ASCII')
					$new_str[$idx] .= $c;
			}
			if (strlen($new_str[$idx]) > $chunklen)
			{
				if ($code == 'US-ASCII')
					$new_str[$idx] = substr($str, $j, strlen($new_str[$idx])-1);
				else
					$new_str[$idx] = substr($str, $j, strlen($new_str[$idx])-2);
				$new_str[++$idx] .= $c;
				$j += $chunklen;
			}
			elseif (strlen($new_str[$idx]) == $chunklen)
			{
				$idx++;
				$j += $chunklen;
			}
			if ($code == 'US-ASCII')
				$i++;
			else
				$i += 2;	
		}
		return implode($new_str, $end);
	}
	
	function euctoimap_utf7_mbstring($str_euc)
	{
		return mb_convert_encoding($str_euc, 'UTF7-IMAP', 'EUC-JP');	
	}
	
	function euctoimap_utf7_jcode($str_euc)
	{
		if (function_exists('imap_utf7_encode'))
			return imap_utf7_encode($str_euc);
		else
			return $str_euc;			// Not Support
	}
	
	function euctoimap_utf7($str_euc)
	{
		if ($this->get_charcode($str_euc) == 'EUC')
		{
 			$func_name = $this->func_name['euctoimap_utf7'];
			return $this->$func_name($str_euc);
		}
		else 
			return $str_euc;
	}
	
	function utf7_imaptoeuc_mbstring($str_utf7_imap)
	{
		return mb_convert_encoding($str_utf7_imap, 'EUC-JP', 'UTF7-IMAP');
	}
	
	function utf7_imaptoeuc_jcode($str_utf7_imap)
	{
		if (function_exists('imap_utf7_decode'))
			return imap_utf7_decode($str_utf7_imap);
		else
			return $str_utf7_imap;		// Not Support
	}
		
	function utf7_imaptoeuc($str_utf7_imap)
	{
 		$func_name = $this->func_name['utf7_imaptoeuc'];
		return $this->$func_name($str_utf7_imap);
	}
	
	function substr($str, $start, $length='')
	{
		if (!function_exists('mb_substr'))
			$result = substr($str, $start, empty($length) ? strlen($str) : $length);
		else
		{
			if (!empty($length))
				$result = mb_substr($str, $start, $length);
			else
				$result = mb_substr($str, $start);
		}
		return $result;			
	}
}
?>
