<?
require_once('include/global.php');
require_once('include/mail_lib.php');
require_once('include/file.php');
require_once('conf.inc.php');

if (!$G_SYS['MAIL_BOX_BACKUP_USE'])
	msg("편지함 백업/복구 기능을 사용할 수 없도록 설정되었습니다.\\n\\n관리자에게 문의하여주시기 바랍니다.", 0, true);

set_time_limit(10800);

// check
	if (!$_GET['mb_id'] || !$_POST['mb_restore_skip'])
		msg('올바른 URL로 접근하여 주십시오');

	$errorMsg = file_upload_error_msg($_FILES['mb_restore_file'], $_FILES['mb_restore_file']['size'], $G_SYS[UPLOAD_MAIL_BOX_RESTORE_MAX_SIZE]);
	if ($errorMsg != '')
		msg("백업파일 업로드가 실패하였습니다.\\n\\n원인 : ".$errorMsg);

// 확장자 제한
	$file_ext = strtolower(file_name_ext($_FILES['mb_restore_file']['name']));
	if (!in_array($file_ext, array('eml', 'zip')))
		msg("업로드할 수 없는 파일 확장자입니다.\\n\\neml, zip 파일만 복구가 가능합니다.\\n\\n - 파일명 : ".$_FILES['mb_restore_file']['name']);


// 남은메일용량체크 - 압축파일기준
	$m_quota = db_get_one("SELECT m_quota FROM " . $TB['MEMBER'] . " WHERE m_no='". $AUTH['auth_m_no'] . "'")*1024;
	$q_hint = ($G_SYS[DB] == 'oracle') ? "/*+ ORDERED index_asc (".$AUTH['auth_m_mf_table']." MF_".$AUTH['auth_d_no']."_".$AUTH['auth_m_mail_file_group']."_MNO_MBID) */" : "";
	$mf_filesize_sum = db_get_one("SELECT ".$q_hint." SUM(mf_filesize) FROM " . $AUTH['auth_m_mf_table'] . " WHERE m_no='". $AUTH['auth_m_no'] . "'");

	$mail_box_free = $m_quota - $mf_filesize_sum;

	if ($mail_box_free - $_FILES['mb_restore_file']['size'] < 1)
	{
		msg("메일용량이 부족하여 복구가 불가능합니다.\\n\\n불필요한 메일을 삭제하여 용량을 확보하고 다시 시도해주십시오.\\n\\n  - 남은메일용량 : ".filesize_human($mail_box_free, 0)."\\n\\n  - 백업파일크기 : ".filesize_human($_FILES['mb_restore_file']['size'], 0));
	}	// if()

?>
<html lang="ko">
<head>
	<meta http-equiv="Content-Type" content="text/html; charset=<?= $G_SYS[CHARSET] ?>">
	<title><?= $G_SYS[SITE_TITLE] ?></title>
	<link rel="STYLESHEET" type="text/css" href="<?= nskindirroot('main') ?>/style.css?v=<?= NM_VER ?>">
	<script language="JavaScript" src="<?= $nmpath ?>/include/global.js?v=<?= NM_VER ?>"></script>
	<base href="<?= $G_SYS['HTTP_URL_ROOT'] ?>/<?= nskindir($NSKIN['view_kind']) ?>/">
</head>
<body>
<h3>편지함 복구를 시작합니다.</h3>
※ 백업파일 용량에 따라 많은 시간이 소요될 수 있으니 잠시만 기다려주시기 바랍니다.<br>
<br>
1. 백업파일 업로드 성공 : <?= $_FILES['mb_restore_file']['name'] ?> (<?= filesize_human($_FILES['mb_restore_file']['size']) ?>)<br>
<?
flush();

// set
	$zip_dir = $UPLOAD_ROOT.'/'.$UPLOAD_DIR[BIGFILE_TMP];
	$zip_ext_dir = 'NmailRestore_'.$_GET['mb_id'].'_'.date('Ymd_His').'_'.getmicrotime();
	$zip_file = $_GET['file'];
	$restore_file_tmp = $zip_dir.'/'.$zip_ext_dir.'/'.$_FILES['mb_restore_file']['name'];
	// [2008-10-22] 일부 UTF-8 환경에서 한글파일명으로 백업/복구가 안되는 문제보완.
	$restore_file_tmp_eng = $zip_dir.'/'.$zip_ext_dir.'/'.basename($_FILES['mb_restore_file']['tmp_name']).'.zip';

// unzip
	$errorMsg = mkdir_parent($UPLOAD_DIR[BIGFILE_TMP].'/'.$zip_ext_dir);
	if ($errorMsg != '')
		msg("복구를 위한 임시 디렉토리 생성이 실패하였습니다.\\n\\n원인 : ".$errorMsg);

	// -o  overwrite files WITHOUT prompting


if ($file_ext == 'zip')
{
	?>
	2. 백업파일 압축해제를 시작합니다...
	<?
		flush();

		// [2008-09-24] 편지함 백업/복구시 사용되는 압축 프로그램 Linux/Windows 구분
		if (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN')
		{
			$unzip_bin = dirname($G_SYS[PAGE_ROOT]).'/tools/7-zip/7za.exe';
			if (!file_exists($unzip_bin))
				error("서버에서 압축프로그램을 찾을 수 없습니다.\n=> " . $unzip_bin, 'FILE');
			$unzip_bin .= ' e -aot';

			$cmd = $unzip_bin.' '.escapeshellarg($_FILES['mb_restore_file']['tmp_name']).' -o'.escapeshellarg($zip_dir.'/'.$zip_ext_dir);

			ob_start();
			//system($cmd);
			passthru($cmd . ' 2>&1', $return_var);
			$cmd_result = ob_get_contents();
			ob_end_clean();
			if ($return_var != 0)
				error("편지함 복구가 실패하였습니다.\n\n복구 명령 : ".$cmd."\n\n복구 명령 결과 : ".$cmd_result, 'FILE');
		} else
		{
			// [2026-01-06] 한글 파일명이 있을 경우 그대로 압축 해제 지원 (한글 파일명이 긴 경우 #Uc2a4 처럼 길어지며 중단되는 것 방지)
			putenv('LANG=ko_KR.UTF-8');

			$zip_bin = '/usr/bin/zip';
			if (!file_exists($zip_bin))
				error("서버에서 압축프로그램을 찾을 수 없습니다.\n=> " . $zip_bin, 'FILE');
			$zip_bin .= ' -q';

			$unzip_bin = '/usr/bin/unzip';
			if (!file_exists($unzip_bin))
				error("서버에서 압축프로그램을 찾을 수 없습니다.\n=> " . $unzip_bin, 'FILE');
			$unzip_bin .= ' -q';

			// [2008-06-17] zip파일내에 한글 파일명이 있을 경우 깨지지 않도록 보완
			move_uploaded_file($_FILES['mb_restore_file']['tmp_name'], $restore_file_tmp_eng);

			$cmd = $zip_bin.' -FF '.escapeshellarg($restore_file_tmp_eng);
			ob_start();
			system($cmd);
			ob_end_clean();

			// [2026-01-07] 다음에서 백업받은 CP949 파일명 압축해제중 "File name too long" 에러 방지하도록 -O UTF-8 추가
			//    ???.eml 로 저장되나, 압축 해제만 되면 임시 파일명으로 저장되므로 무관함
//			$cmd = $unzip_bin.' -o '.escapeshellarg($restore_file_tmp_eng).' -d '.escapeshellarg($zip_dir.'/'.$zip_ext_dir);
			$cmd = $unzip_bin.' -O UTF-8 -o '.escapeshellarg($restore_file_tmp_eng).' -d '.escapeshellarg($zip_dir.'/'.$zip_ext_dir);
			ob_start();
			system($cmd . ' 2>&1', $return_var);
			$cmd_result = ob_get_contents();
			ob_end_clean();

			unlink($restore_file_tmp_eng);

			if ($return_var != 0)
				error("편지함 복구가 실패하였습니다.\n\n복구 명령 : ".$cmd."\n\n복구 명령 결과 : ".$cmd_result, 'FILE');
		}	// if()

		errorlog("편지함 복구, zip 파일 압축 해제\n\n복구 명령 : ".$cmd."\n\n복구 명령 결과 : ".$cmd_result, 'FILE');
	?>
	[완료]<br>
	3. 편지함에 복구할 메일데이타를 추가합니다.<br>
	<?
	flush();
} else
{
	// [2011-01-25] Windows + UTF8 - 한글 파일명 예외 처리
	$_file_new = $_FILES['mb_restore_file']['name'];
	$_file_new = file_name_char_limit($_file_new);

	// [2025-11-13] Windows는 파일 경로 포함 최고 260자이므로 파일명 120자 이내로 제한하도록 수정.
	if (strlen($_file_new) > 120 && strtoupper(substr(PHP_OS, 0, 3)) === 'WIN')
		$_file_new = substr($_file_new, 0, 116).'.eml';

	if (preg_match('/[^\x00-\x7F]/', $_file_new))
	{
		$_file_new = md5_file($_FILES['mb_restore_file']['tmp_name']).'.eml';
	}	// if()
	//move_uploaded_file($_FILES['mb_restore_file']['tmp_name'], $restore_file_tmp);
	move_uploaded_file($_FILES['mb_restore_file']['tmp_name'], $zip_dir.'/'.$zip_ext_dir.'/'.$_file_new);
}	// if()


// 메일 추가
	$mail_dir = get_mail_dir().'/'.get_mb_dir($_GET['mb_id']);

	$skip_cnt = 0;
	$proc_cnt = 0;

	if ($dh = opendir($zip_dir.'/'.$zip_ext_dir)) {
		while (($file = readdir($dh)) !== false) {
			// .eml 확장자를 가진 파일만 처리함.
			if ($file!="." && $file!=".." && strtolower(file_name_ext($file)) == 'eml' && is_file($zip_dir.'/'.$zip_ext_dir.'/'.$file))
			{
				// [2009-05-06] 파일명에 2byte문자가 들어간 경우 파일명 변경.
					$filemtime = filemtime($zip_dir.'/'.$zip_ext_dir.'/'.$file);
					$file_new = file_name_char_limit($file);
					// [2012-03-29] 파일명이 공백이 들어갈 경우 Office Outlook 에서 POP3로 메일을 받아갈째 중복 체크가 안되는 문제 보완.
					$file_new = str_replace(' ', '_', $file_new);

					// [2026-01-06] 파일명이 영문숫자.,_ 문자열이 아닌 경우 파일명 변경 처리(중복 처리 및 POP3 장애 예방)
					if ( ! preg_match('/^[a-z0-9.,_-]+\.eml$/i', $file_new))
					{
						if ($file_ext == 'zip')     // 파일수정일시.md5해시.eml
						{
							// [2026-01-07] Windows 에서 한글파일명은 md5_file() 에서 찾을 수 없어, 임시 영문숫자파일명으로 변경
							if (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN') {
								$win_tmp_file = '_tmp_' . getmicrotime() . mt_rand(0,999) . '.tmp';
								if (rename($zip_dir.'/'.$zip_ext_dir.'/'.$file, $zip_dir.'/'.$zip_ext_dir.'/'.$win_tmp_file)) {
									$file = $win_tmp_file;
								} else {
									error("복구시 임시 파일명으로 변경이 실패하였습니다.\n" . $file . " => " . $unzip_bin, 'FILE');
								}
							}
							$file_new =	$filemtime.'.'.md5_file($zip_dir.'/'.$zip_ext_dir.'/'.$file).'.eml';
						} else		// eml 파일만 올린 경우, 파일수정시간이 업로드시간이므로 중복체크가 안되므로 제외함.
						{
							$file_new =	md5_file($zip_dir.'/'.$zip_ext_dir.'/'.$file).'.eml';
						}	// if()
					} else if (strlen($file_new) > 120) {
						// [2025-11-13] 120자 이내로 제한하도록 수정.
						$file_new = substr($file_new, 0, 116).'.eml';
					}	// if()

				// 중복체크
				if (file_exists($mail_dir.'/'.$file_new))
				{
					if ($_POST['mb_restore_skip'] == '1')		// 중복된 메일 생략
					{
						$skip_cnt++;
						continue;
					} else		// 중복되었을 경우 파일명 변경
					{
						for ($i=0; $i<100; $i++)
						{
							$file_new = str_replace('.eml', '.'.rand(111,999).'.eml', $file_new);
							if (!file_exists($mail_dir.'/'.$file_new))
								break;
						}	// for()
					}	// if()
				} else
				{
					// [2013-02-27] 편지함 백업시 파일명의 확장자가 .eml 이 아닐 경우, .eml을 자동으로 붙이기(기본값은 false)
					if ($G_SYS['MAIL_BOX_BACKUP_FILENAME_EML_AUTOADD'] && $_POST['mb_restore_skip'] == '1')
					{
						// 중복된 메일 생략 - .eml 이 없는 경우도 검사함.
						if (file_exists($mail_dir.'/'.substr($file_new, 0, strlen($file_new)-4)))
						{
							$skip_cnt++;
							continue;
						}	// if()
					}	// if()
				}	// if()

				$filesize = filesize($zip_dir.'/'.$zip_ext_dir.'/'.$file);

				// 남은메일용량체크 - 압축파일기준
					$mail_box_free -= $filesize;
					if ($mail_box_free < 1)
					{
						msg("메일용량이 부족하여 복구가 중단되었습니다.\\n\\n불필요한 메일을 삭제하여 용량을 확보하고 다시 시도해주십시오.");
					}	// if()


				// crlf 처리
					$fd = fopen($zip_dir.'/'.$zip_ext_dir.'/'.$file, "r");
					$contents = fread($fd, $filesize);
					fclose($fd);

					// [2007-12-13]
					//$sp = strpos($contents, "\r\n");
					$sp = strpos(str_replace("\r\n", "", $contents), "\n");

					//if ($sp === false)
					if ($sp !== false)
					{
						//$contents2 = str_replace("\n", "\r\n", $contents);
						$contents2 = str_replace("\n", "\r\n", str_replace("\r\n", "\n", $contents));
						if (strcmp($contents, $contents2))
						{
							$fh = fopen($zip_dir.'/'.$zip_ext_dir.'/'.$file, 'w');
							fwrite($fh, $contents2);
							fclose($fh);
							touch($zip_dir.'/'.$zip_ext_dir.'/'.$file, $filemtime);
						}	// if()
					}	// if()


				// 메일 파일 복사
					$rename = rename($zip_dir.'/'.$zip_ext_dir.'/'.$file, $mail_dir.'/'.$file_new);


				// DB Insert
					if ($rename)
					{
						$DEBUG['proc_insert_mailparse']['start'] = getmicrotime();
						$data = get_mailparse_body_dbdata($mail_dir.'/'.$file_new);
						$DEBUG['proc_insert_mailparse']['exec'] += getmicrotime() - $DEBUG['proc_insert_mailparse']['start'];

						$DEBUG['proc_insert_db']['start'] = getmicrotime();
						$data['m_no'] = $AUTH['auth_m_no'];
						$data['mb_id'] = $_GET['mb_id'];
						$data['mf_is_read'] = 'N';
						mail_db_insert($AUTH[auth_m_mf_table], $data, false);
						$DEBUG['proc_insert_db']['exec'] += getmicrotime() - $DEBUG['proc_insert_db']['start'];
					}	// if()

					$proc_cnt++;

					if ($proc_cnt%10 == 0)
					{
						echo ".";
						if ($proc_cnt%1000 == 0)
							echo "<br>";
						flush();

						// [2011-06-07] 튜닝
						if ($proc_cnt%100 == 0)
							usleep(200000);

						if ($proc_cnt%1000 == 0)
							sleep(1);
					}	// if()
			}
		}
		closedir($dh);
	} else
	{
		errorlog("복구를 위한 임시 디렉토리의 퍼미션이 잘못되어 실패하였습니다.\n=> " . $zip_dir.'/'.$zip_ext_dir, 'FILE');
	}	// if()



	// 완료후 임시 디렉토리 삭제
	if (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN')
	{
		$cmd_rm = 'rmdir/q/s';
	} else
	{
		$cmd_rm = 'rm -rf';
	}
	if ($zip_dir != '' && strpos($zip_ext_dir, 'NmailRestore_') !== false)		// 프로그램상의 미스로 인하여 / 파티션이 삭제되는 것 예방.
		system($cmd_rm.' '.escapeshellarg(realpath($zip_dir.'/'.$zip_ext_dir.'/')));


	if ($skip_cnt > 0 || $proc_cnt > 0)
	{
		$msg = "편지함 복구가 완료되었습니다.\\n\\n  - 중복된 메일 생략 : ".number_format($skip_cnt)."통\\n\\n  - 복구된 메일 : ".number_format($proc_cnt)."통";
	} else
	{
		$msg = "편지함 복구가 실패하였습니다.\\n\\n복구 가능한 eml 파일이 없으니 파일 내용을 확인해보십시오.\\n\\n일부 다른 메일 서비스에서 백업 받은 zip 파일의 압축이 정상적으로 풀리지 않을 수 있습니다.\\n\\n이 경우 PC에서 압축을 해제후, 다시 압축하여 복구를 시도해보시기 바랍니다.";
	}	// if()

?>
<script language="JavaScript">
<!--
	if (confirm("<?= $msg ?>\n\n복구작업을 계속하시겠습니까?"))
	{
		try
		{
			opener.window.location.reload();
		} catch (e) {}
		location.href = "<?= $nmpath ?>/mail_box_restore.php?<?= get_qs() ?>";
	} else
	{
		try
		{
			opener.window.location.reload();
		} catch (e) {}
		window.close();
	}	// if()
//-->
</script>

<?
require_once('include/global_end.php');
?>
</body>
</html>