<?

// 중복 include 방지
if ( defined("_INCLUDED_FILE") ) return;
define("_INCLUDED_FILE", "1");


/** shared variables

*/

$UPLOAD;
$UPLOAD_ROOT;
$UPLOAD_MAX_SIZE;
$CHMOD_CHANGE;
$UPLOAD_ISHIDDEN;
$G_SYS[URL_ROOT];

/** File upload

	# 기능
		저장할 디렉토리가 없을경우 자동생성
		저장할 디스크의 남은 공간 검사
		파일 용량, 확장자 검사
		업로드파일에 보안확장자를 덧붙인뒤 지정된 디렉토리에 복사

*/

function file_up_new($key, $save_name, $save_name_key, $upload_dir, $upload_max)
{
	return file_up($_FILES[$key]['tmp_name'], $save_name, $_FILES[$key]['size'], $upload_dir, $save_name_key, "ALL", NULL, $upload_max, 10, $_FILES[$key]['error']);
}	// function()

function file_up($userfile, $userfile_name, $userfile_size, $userfile_dir, $userfile_postfix="noexec", $userfile_allow_ext="ALL", $userfile_newname=null, $userfile_size_lmt="DEFAULT", $userfile_size_lmt_rate=3, $error=0)
{

	# Required variables
		//global $HTTP_POST_FILES;
		global $UPLOAD_ROOT;		// Download root directory  ex) /home/httpd/upload,  [global_define.php]
		global $UPLOAD_MAX_SIZE;		// 업로드 파일 최대크기.  ex) 2MB = 1024*1024*2
		global $UPLOAD;		// file ext list
		global $CHMOD_CHANGE;		// 업로드파일 권한 ex) 0707
		$userfile;
		$userfile_name;
		$userfile_size;
		$userfile_dir;		// Download sub directory  ex) /intropage
		$userfile_allow_ext;		// 파일확장자 제한종류 (ALL - 제한없음, IMG - 이미지 파일만)
		$userfile_size_lmt;		// Max of uploading file size
		$userfile_size_lmt_rate;		// Rate of uploading file size (업로드될 파일에 이 수를 곱한뒤, 디스크의 남은공간이 이보다 클때만 업로드 가능하게함),  사용안함(0)
		$userfile_postfix;		// 업로드된 파일뒤에 붙을 확장자(파일 보안기능)
		$userfile_newname;		// 업로드시 다른 이름으로 저장할때 사용될 파일이름.

	# upload max size
		if ($userfile_size_lmt == "DEFAULT") $userfile_size_lmt = $UPLOAD_MAX_SIZE;

	// [2006-07-28] 업로드 파일 용량 체크 변경.
		if ($error)
			return "\\n\\n[파일업로드 실패] 파일크기가 제한된 크기인 " . number_format($userfile_size_lmt / 1024 / 1024) . "MB 를 초과하였거나 0byte입니다.";

	# Directory check.
		// ex) $UPLOAD_ROOT . "/" . $userfile_dir = " /home/httpd/upload/intropage";
		if ( !is_dir($UPLOAD_ROOT . "/" . $userfile_dir) )		// 저장할 디렉토리가 없을때 생성이 가능할경우 생성해주고 넘어감.
		{
			// 저장할 디렉토리 생성.
			if ( is_writable($UPLOAD_ROOT) )		// 업로드 루트 디렉토리에서 쓰기권한이 있을때만 가능.
			{
				// 2단계이상의 디렉토리 생성하기
				$ex_dir = explode("/", $userfile_dir);
				for ($i=0; $i<sizeof($ex_dir); $i++)
				{
					// 단계별 디렉토리명 얻기.  ex) intropage, intropage/data1, intropage/data1/a01
					$ex_dir2 = "";
					for ($j=0; $j<=$i; $j++)
					{
						if ($j > 0) $ex_dir2 .= "/";
						$ex_dir2 .= $ex_dir[$j];
					}
					if ( !is_dir($UPLOAD_ROOT . "/" . $ex_dir2) )
					{
						if ( !mkdir($UPLOAD_ROOT . "/" . $ex_dir2, $CHMOD_CHANGE) )
						{
							return "\\n\\n[시스템오류]\\n파일 업로드가 실패하였습니다.\\n저장할 디렉토리가 존재하지 않습니다.\\n관리자에게 문의하여 주십시오.";
						}

						// root권한이 없는 계정사용자일경우라도 업로드파일이 관리가능토록 모든 권한을 모두에게 허용함.
						chmod($UPLOAD_ROOT . "/" . $ex_dir2, $CHMOD_CHANGE);

					}	// if()
				}	// for()
			}else{
				return "\\n\\n[시스템오류]\\n파일 업로드가 실패하였습니다.\\n저장할 디렉토리가 존재하지 않습니다.\\n관리자에게 문의하여 주십시오.";
			}	// if()

		}else if ( !is_writable($UPLOAD_ROOT . "/" . $userfile_dir) )		// 저장할 디렉토리에서 쓰기 권한이 없을때 작업중단.
		{
				return "\\n\\n[시스템오류]\\n파일 업로드가 실패하였습니다.\\n저장할 디렉토리에서 쓰기권한이 없습니다.\\n관리자에게 문의하여 주십시오.";
		}	// if()


	# Disk free space check
		// [2007-08-24] 업로드 비율을 체크하지 않도록 함.
		/*
		if ( diskfreespace($UPLOAD_ROOT . "/" . $userfile_dir) < ($userfile_size_lmt*$userfile_size_lmt_rate) )		// 저장공간이 업로드 파일크기 제한비율을 초과할 경우  작업중단.
		{
			return "\\n\\n[시스템오류]\\n파일 업로드가 실패하였습니다.\\n디스크의 남은공간이 부족합니다.\\n관리자에게 문의하여 주십시오.";
		}	// if()
		*/

	# File check & Upload
		if ( !is_array($userfile) ) $userfile = (array)$userfile;
		if ( !is_array($userfile_name) ) $userfile_name = (array)$userfile_name;
		if ( !is_array($userfile_size) ) $userfile_size = (array)$userfile_size;
		if ( !is_array($userfile_newname) ) $userfile_newname = (array)$userfile_newname;

		for ($fno=0; $fno<sizeof($userfile); $fno++)
		{
			// 업로드여부 검사
				if (!is_uploaded_file($userfile[$fno]))
				{
					if ($userfile_name[$fno])		// 업로드 시도후 실패한 경우
					{
						$errorMsg[$fno] .= "\\n\\n[파일업로드 실패 - " . $userfile_name[$fno] . "] 파일크기가 제한된 크기인 " . number_format($userfile_size_lmt / 1024 / 1024) . "MB 를 초과하였거나 0byte입니다.";
					}
					continue;	// for()
				}

			// 파일 크기 제한
				/*  파일크기 초과시 0byte로 처리됨
				if ($userfile_size[$fno] > $userfile_size_lmt)		// 제한된 파일크기를 초과할때 작업중단.  ( php.ini에 설정된 값을 초과할경우는 php 자체적으로 업로드를 취소시킴. )
				{
					$errorMsg[$fno] .= "\\n\\n[파일업로드 실패 - " . $userfile_name[$fno] . "] " . number_format($userfile_size_lmt / 1024 / 1024) . "MB 이내의 파일만 업로드가 가능합니다.";
					continue;	// for()
				}	// if()
				*/

			// 파일확장자 제한
				$userfile_ext = file_name_ext($userfile_name[$fno]);		// 파일 확장자 알아내기

				$chk_equal = "N";		// 확장자 일치여부 (기본 : N)
				switch($userfile_allow_ext)
				{
					case "IMG":
						// 허가 목록
							$view_ext_list = "";
							for ($u=0; $u<sizeof($UPLOAD[FILTER_EXT][IMG]); $u++)
							{
								if ($u > 0) $view_ext_list .= ", ";
								$view_ext_list .= strtoupper($UPLOAD[FILTER_EXT][IMG][$u]);
							}	// for()

						// 일치여부 검사
							for ($u=0; $u<sizeof($UPLOAD[FILTER_EXT][IMG]); $u++)
							{
								if ( strtoupper($userfile_ext) == strtoupper($UPLOAD[FILTER_EXT][IMG][$u]) ) {
									$chk_equal = "Y";
									break;
								}	// if()
							}	// for()

						// 검사결과에 따른 진행여부 처리
							if ($chk_equal == "N")		// 일치하는 확장자가 없을때 업로드 제한함.
							{
								$errorMsg[$fno] .= "\\n\\n[파일업로드 실패 - " . $userfile_name[$fno] . "] 이미지 파일만 올리실 수 있습니다.\\n허가된파일) " . $view_ext_list;
								continue 2;	// switch(), for()
							}	// if()

						break;

					default:		// "ALL"이거나 잘못된 입력값일때
						break;

				}	// switch()


			// [User] File save
				if ( $userfile_newname[$fno] )		// 새로 지정할 이름이 있을때
				{
					$save_filename = $userfile_newname[$fno];
				}else		// 기존의 이름을 그대로 사용할 때
				{
					$save_filename = $userfile_name[$fno];
				}	// if()

				$save_filename = stripslashes($save_filename);

				// [2008-04-08] Windows + UTF-8 환경
				global $G_SYS;
				if (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN' && strtoupper($G_SYS[CHARSET]) == 'UTF-8')
					$save_filename = file_name_char_limit(iconv_fix('UTF-8', $save_filename, 'CP949'));

				// 보안기능의 확장자 덧붙여서 저장함.
				$mv_up_file = $UPLOAD_ROOT . "/" . $userfile_dir . "/" . file_name_fix($save_filename, $userfile_postfix);
				if (!move_uploaded_file($userfile[$fno], $mv_up_file))
				{
					$errorMsg[$fno] .= "\\n\\n[파일업로드 실패 - " . $save_filename . "] 파일저장이 실패했습니다.";
					continue;	// for()
				}	// if()

				// root권한이 없는 계정사용자일경우라도 업로드파일이 관리가능토록 모든 권한을 모두에게 허용함.
				chmod($UPLOAD_ROOT . "/" . $userfile_dir . "/" . file_name_fix($save_filename, $userfile_postfix), $CHMOD_CHANGE);

				file_debug(__FUNCTION__, $mv_up_file);

		}	// for()

	# Error Message Full
		for ($i=0; $i<sizeof($userfile); $i++)
		{
			$errorMsgFull .= $errorMsg[$i];
		}	// for()

	return $errorMsgFull;

}	// function()



/** File download (string filename, string file key, string file upload dir)

	# 기능
		무단링크방지 ( 타사이트에서 다운불가 )
		파일경로숨기기 (사용자에게 파일의 경로를 보여주지 않음)
		부모 디렉토리로의 임의접근 차단 (/etc/passwd 등)

*/
function file_down($name, $key, $dir="", $subtype='octet-stream', $realname='', $isimg=false)
{
	# Required variables
		global $HTTP_HOST;		// Host url (ex. www.domain.com)
		global $HTTP_REFERER;		// Previous url (Query String은 제외됨)
		global $UPLOAD_ROOT;		// Download root directory  ex) /home/httpd/upload,  [global_define.php]
		$name;		// Download file name
		$key;		// Primary key or Unique value
		$dir;		// Download sub directory  ex) /intropage


	#  Authorized url check
		/*
		$org_url = "http://" . $HTTP_HOST;		// ex) www.domain.com (파일이 저장된 곳의 HTTP_HOST)
		if (!eregi($org_url, $HTTP_REFERER))
		{
			echo ("<script language=\"JavaScript\">
			alert('현재 파일은 링크방지 조치가 되어있습니다.\\n\\n$org_url 내에서만 파일을 받을 수 있습니다.');
			location.replace('$org_url');
			</script>");
			exit;
		}	// if()
		*/


	# Download file check
		$name = stripslashes($name);

		// [2008-04-08] Windows + UTF-8 환경
		global $G_SYS;
		if (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN' && strtoupper($G_SYS[CHARSET]) == 'UTF-8')
			$name = file_name_char_limit(iconv_fix('UTF-8', $name, 'CP949'));


		$file = $UPLOAD_ROOT . "/" . $dir . "/" . file_name_fix($name, $key);		// 다른 디렉토리 /etc, /usr, /var 등은 접근불가

		// [secure] 부모 디렉토리로의 임의접근 차단 ex) [../]
		// [2015-04] PHP5.4.x대응 대체함수 적용
        // [2020-08] KVE 경로 취약점 개선
		#$file = ereg_replace("(\.\.\/)", "", $file);
        $file = preg_replace("/(\.\.\.\.\/\/)/", "", $file);
		$file = preg_replace("/(\.\.\/)/", "", $file);
        $file = preg_replace("/(\.\.\\\)/", "", $file);

		if ( !file_exists($file) )
		{
			return "\\n\\n[파일받기오류]\\n해당 파일이 존재하지 않습니다.";
		}else if ( !is_readable($file) )
		{
			return "\\n\\n[파일받기오류]\\n해당 파일에 읽기권한이 없습니다.\\n\\n관리자에게 문의하여 주십시오.";
		}	// if()


	# Downloading
		// [2008-01-24] 다운로드받을 파일명을 지정할 수 있도록 함.
		if ($realname != '')
		{
			$file_name = $realname;
		} else
		{
			$file_name = file_name_unfix(basename_fix($file), $key);		// 실제이름으로 변환.

			// [2008-04-08] Windows + UTF-8 환경
			global $G_SYS;
			if (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN' && strtoupper($G_SYS[CHARSET]) == 'UTF-8')
				$file_name = file_name_char_limit(iconv_fix('CP949', $file_name, 'UTF-8'));
		}	// if()

	// [2008-01-24] 대용량 다운로드 지원
		$file_size = filesize($file);

		file_down_headeronly(NULL, $file_name, $subtype, $file, $file_size, $isimg);

		$fp = fopen($file,"r");
		while (!feof($fp))
			echo fread($fp,8192);
		fclose($fp);
}	// function()


/*
	[2005-07-05]
	-. 파일다운로드용 헤더 및 본문만 출력
*/
function file_down_headeronly($contents, $file_name, $subtype='octet-stream', $file=NULL, $file_size=NULL, $isimg=false)
{
	global $G_SYS;

	// [2012-12-06] 파일 다운로드시 페이지 이동 지원.
	session_write_close();

	// [2012-12-12] db disconnect
	unset_db();

	// [2008-04-03] 파일 다운로드 시간 제한
		if (isset($G_SYS['DOWNLOAD_TIME_LIMIT']))
			set_time_limit($G_SYS['DOWNLOAD_TIME_LIMIT']);

	// [2006-12-13] mime.types 지정, 기존 $subtype은 무시하고 호환성을 위해 놔둠.
	if (!function_exists('mime_content_type_simple')) {
	   function mime_content_type_simple($filename) {
		   // [2015-10-01] Strict 오류 메시지 개선
		   #$idx = strtolower(end( explode( '.', $filename )) );
		   $tmp_idx = explode( '.', $filename );
		   $idx = strtolower(end($tmp_idx) );
		   $mimet = array(
			   'ai' =>'application/postscript',
			   'aif' =>'audio/x-aiff',
			   'aifc' =>'audio/x-aiff',
			   'xyz' =>'chemical/x-xyz',
			   'zip' =>'application/zip',
			   'xls' =>'application/vnd.ms-excel',
			   'ppt' =>'application/mspowerpoint',
			   'doc' =>'application/msword',
			   'htm' =>'text/html',
			   'html' =>'text/html',
			   'eml' =>'message/rfc822',
			   'txt' =>'text/plain',
			   'pdf' =>'application/pdf',
			   'jpg' =>'image/jpeg',
			   'gif' =>'image/gif',
			   'png' =>'image/png',
			   'svg' =>'image/svg+xml',
			   'dwg' =>'application/acad',
			   'dxf' =>'application/dxf',
			   'swf' =>'application/x-shockwave-flash'
		   );

		   if (isset( $mimet[$idx] )) {
			   return $mimet[$idx];
		   } else {
			   return 'application/octet-stream';
		   }
	   }
	}
	$c_type = mime_content_type_simple($file_name);

	// 윈도우에서 지원하지 않는 문자는 파일명에서 자동 치환하기
	$file_name = file_name_char_limit($file_name);

	// [2006-09-07] UTF-8로 변경후 한글파일명이 다운로드 되지 않던 문제 해결.
	// [2007-07-11] IE7 에서 일부 한글파일이 바로 열리지 않던 문제 수정.  익스플로어만 한글로 변환해서 바로 출력시킴.
	// [2008-02-25] UTF-8 환경일때 IE에서 일부 외국어 파일이 깨지는 오류 수정.
	// [2013-10-28] IE 11 fix
	//if (strpos($_SERVER['HTTP_USER_AGENT'], 'MSIE') !== false)
	$file_name_fallback = null;
	if (strpos($_SERVER['HTTP_USER_AGENT'],"MSIE") !== false || strpos($_SERVER['HTTP_USER_AGENT'], 'Trident') !== false)
	{
		// [2006-12-11][다운로드]첨부파일명에 세미콜론(;)이 들어간 경우 파일명이 잘리던 오류 수정.
		// 파이어폭스에선 잘 받아지지만 익스플로어에서는 세미콜론(;)에서 잘림.
		$file_name = str_replace(";", "%3B", $file_name);

		// [2007-11-22] 외국어메일 보기에서의 첨부파일 다운
		if ($_GET['mf_charset'] != '')
		{
			$file_name = iconv_fix($_GET['mf_charset'], $file_name, 'UTF-8');
		} else if (strtoupper($G_SYS[CHARSET]) != 'UTF-8')
		{
			$file_name = iconv_fix($G_SYS[CHARSET], $file_name, 'UTF-8');
		}	// if()
		// [2008-04-08] 한글 첨부파일을 저장하지 않고 바로 열었을 때 파일명이 제대로 보이도록 함. (EUC-KR 환경일때만 적용)
		// [2008-06-18] UTF-8 환경에도 동일하게 적용.
		/*
		if (strtoupper($G_SYS[CHARSET]) == 'UTF-8')
		{
			$file_name = rawurlencode($file_name);
		} else
		{
		*/
			$file_name = iconv_fix('UTF-8', $file_name, 'CP949');
			$file_name = file_name_char_limit($file_name);
		//}	// if()
	} else if ($_GET['mf_charset'] != '' && strtoupper($_GET['mf_charset']) != 'UTF-8')
	{
		// [2007-11-22] 외국어메일 보기에서의 첨부파일 다운
		$file_name = iconv_fix($_GET['mf_charset'], $file_name, 'UTF-8');
	} else if (preg_match('/Android/', $_SERVER['HTTP_USER_AGENT']))
	{
		// [2012-04-30] 모바일웹 - Android
		if (strtoupper($G_SYS[CHARSET]) != 'UTF-8')
			$file_name = iconv_fix($G_SYS[CHARSET], $file_name, 'UTF-8');
		$file_name = rawurlencode($file_name);
	} else if (preg_match("/Edge/",$_SERVER['HTTP_USER_AGENT']))
    {
	    // [2018-10-15] 엣지브라우져 한글 첨부파일명 깨짐 문제개선
        $file_name = urlencode($file_name);
	} else
	{
		// [2022-12-14] iOS 사파리 브라우저에서 한글 파일명 깨짐 해결
		$file_name_fallback = $file_name;
	}

	// [2007-05-29]파일의 마지막 수정시간.
	$mtime = false;
	if ($file !== NULL)
		$mtime = filemtime($file);
	if (!$mtime)
		$mtime = time();
	// [2010-12-01] RFC 1123 - HTTP header date fix
	//header('Last-Modified: '.date('r', $mtime));
	header('Last-Modified: '.gmdate('D, d M Y H:i:s \G\M\T', $mtime));

	// [2008-01-24] 대용량 다운로드 지원
	if ($file_size === NULL)
	{
		$length = strlen($contents);
	} else
	{
		$length = $file_size;
	}	// if()

	// [2008-03-26] 이미지 파일을 30일간 웹브라우저에 캐쉬를 남기도록 함.
	if ($isimg)
		header('Cache-Control: max-age=2592000');

	// 브라우저 골라서 헤더를 따로 따로 전송 해 준다.
	// [2006-10-16] [FIREFOX]다운로드시 첨부파일명에 공백이 들어갔을 경우 파일명이 잘리는 오류 수정.  ex) filename="xxx"
	if ( strstr($_SERVER['HTTP_USER_AGENT'],"MSIE 5.5"))
	{
		header("Content-Type: doesn/matter\r\n");
		header("Content-Disposition: filename=\"$file_name\"\r\n\r\n");
		header("Content-Length: ".$length."\r\n");
		header("Content-Transfer-Encoding: binary\r\n");
	}else
	{
		header("Content-Type: $c_type\r\n");

		// [2023-11-17] 첨부파일 다운로드, 인라인(바로 열기) 구분
		$disposition = 'attachment';
		if ($_GET['disposition'] === 'inline')
		{
			$disposition = 'inline';
		}

		if ($file_name_fallback !== null)
		{
			// 응답 결과) content-disposition: attachment; filename="gitlab - ë³µì‚¬ë³¸.png"; filename*=UTF-8''gitlab%20-%20%EB%B3%B5%EC%82%AC%EB%B3%B8.png
			$contentDisposition = $disposition . "; filename=\"$file_name\"; filename*=UTF-8''" . rawurlencode($file_name_fallback);
			header("Content-Disposition: " . $contentDisposition . "\r\n\r\n");
		} else
		{
			header("Content-Disposition: " . $disposition . "; filename=\"$file_name\"\r\n\r\n");
		}
		header("Content-Length: ".$length."\r\n");
		header("Content-Transfer-Encoding: binary\r\n");
	}	// if()


	// [2008-01-24] 대용량 다운로드 지원
	if ($file_size === NULL)
	{
		// [2009-02-16] 일부 네트워크에서 첨부파일 다운로드시 발생하는 오류 예방.
		for ($c=0; $c <= $length-1; $c += 8192)
			echo substr($contents, $c, 8192);
	}	// if()
}	// function()




/** File delete

	# 기능
		파일 존재유무, 삭제권한유무 확인후 삭제

*/
function file_del($userfile_name, $userfile_key, $userfile_dir="", $userfile_exists=TRUE)
{
	# Required variables
		global $UPLOAD_ROOT;		// Download root directory  ex) /home/httpd/upload,  [global_define.php]
		$userfile_name;		// Download file name
		$userfile_key;		// Primary key or Unique value
		$userfile_dir;		// Download sub directory  ex) /intropage
		$userfile_exists;		// 삭제하려는 파일이 반드시 존재해야 하는지 여부 (error massage 에만 영향을 미침)


	# delete
		if ( !is_array($userfile_name) ) $userfile_name = (array)$userfile_name;

		for ($i=0; $i<sizeof($userfile_name); $i++)
		{
			// [2008-04-08] Windows + UTF-8 환경
			global $G_SYS;
			if (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN' && strtoupper($G_SYS[CHARSET]) == 'UTF-8')
				$userfile_name[$i] = file_name_char_limit(iconv_fix('UTF-8', $userfile_name[$i], 'CP949'));


			if ( !$userfile_name[$i] ) continue;
			$userfile = $UPLOAD_ROOT . "/" . $userfile_dir . "/" . file_name_fix($userfile_name[$i], $userfile_key);
			if (dir_parent_limit($userfile_name[$i]))
			{
				$errorMsg .= "\\n\\n[파일삭제 실패 - " . $userfile_name[$i] . "] 상위 디렉토리로는 접근하실 수 없습니다.";
			} else if ( !file_exists($userfile) )
			{
				// [2006-03-08] 파일이 없을때의 에러를 무시할 경우, 해당 디렉토리가 존재하는지 체크함.
				if ( $userfile_exists == TRUE )
				{
					$errorMsg .= "\\n\\n[파일삭제 실패 - " . $userfile_name[$i] . "] 파일이 존재하지 않습니다.";
				} else
				{
					if (!is_dir(dirname($userfile)))
					{
						$errorMsg .= "\\n\\n[파일삭제 실패 - " . $userfile_name[$i] . "] ".dirname($userfile)." 디렉토리가 존재하지 않습니다.";
					}	// if()
				}	// if()
			}else if ( !is_writable($userfile) )
			{
				$errorMsg .= "\\n\\n[파일삭제 실패 - " . $userfile_name[$i] . "] 파일 삭제권한이 없습니다.";
			}else if ( !unlink($userfile) )
			{
				$errorMsg .= "\\n\\n[파일삭제 실패 - " . $userfile_name[$i] . "] 예기치 못한 오류입니다.";
			} else
			{
				errorlog("[file_del] " . $userfile, 'FILEDEL');

				file_debug(__FUNCTION__, $userfile);
			}	// if()
		}	// for()

	return $errorMsg;
}

// [2005-12-14] 디렉토리 하위 전체 삭제.
function dir_del_all($userfile_dir, $isexit=true)
{
	global $UPLOAD_ROOT;

	if (!$userfile_dir)
	{
		error("디렉토리가 입력되지 않았습니다.");
	}	// if()

	if (dir_parent_limit($userfile_dir))
		die("상위 디렉토리로는 접근하실 수 없습니다.");

	$dir = $UPLOAD_ROOT . "/" . $userfile_dir . "/";
	if (is_dir($dir))		// 디렉토리가 존재할때만 삭제시도.
	{
		if (is_writable($dir))
		{
			if (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN')
			{
				exec("rmdir/q/s ".realpath($dir));
			} else
			{
				exec("rm -rf $dir");
			}	// if()

			errorlog("[dir_del_all] " . $dir, 'FILEDEL');

			file_debug(__FUNCTION__, $dir);
		} else
		{
			error("데이타 디렉토리에 퍼미션 오류가 있어서 삭제하지 못했습니다.\n=> " . $dir, 'FILE', $isexit);
		}	// if()
	}	// if()
}


/** File move

	# 기능
		파일 존재유무, 이동권한유무 확인후 이동

	[2002-06-07]
	- 대상디렉토리 생성 오류 수정.

	[2005-07-19]
	-. copy(), unlink() 를 rename() 으로 대체.

*/
function file_move($userfile_name, $userfile_key, $userfile_dir="", $target_name, $target_key, $target_dir="", $userfile_exists=TRUE)
{
	# Required variables
		global $UPLOAD_ROOT;		// root directory  ex) /home/httpd/upload,  [global_define.php]
		$userfile_name;		// User file name
		$userfile_key;		// Primary key or Unique value
		$userfile_dir;		// User sub directory  ex) /intropage
		$userfile_exists;		// 이동하려는 파일이 반드시 존재해야 하는지 여부 (error massage 에만 영향을 미침)


	# move
		if ( !is_array($userfile_name) ) $userfile_name = (array)$userfile_name;
		// [2008-02-14] 이동할 파일명이 다를 경우에 바뀌지 않던 오류 수정
		if ( !is_array($target_name) ) $target_name = (array)$target_name;

		for ($i=0; $i<sizeof($userfile_name); $i++)
		{
			if ( !$userfile_name[$i] ) continue;
			$userfile = $UPLOAD_ROOT . "/" . $userfile_dir . "/" . file_name_fix($userfile_name[$i], $userfile_key);
			// [2008-02-14] 이동할 파일명이 다를 경우에 바뀌지 않던 오류 수정
			//$targetfile = $UPLOAD_ROOT . "/" . $target_dir . "/" . file_name_fix($userfile_name[$i], $target_key);
			$targetfile = $UPLOAD_ROOT . "/" . $target_dir . "/" . file_name_fix($target_name[$i], $target_key);
			if ( !file_exists($userfile) )
			{
				// [2006-03-08] 파일이 없을때의 에러를 무시할 경우, 해당 디렉토리가 존재하는지 체크함.
				if ( $userfile_exists == TRUE )
				{
					$errorMsg .= "\\n\\n[파일이동 실패 - " . $userfile_name[$i] . "] 파일이 존재하지 않습니다.";
				} else
				{
					if (!is_dir(dirname($userfile)))
					{
						$errorMsg .= "\\n\\n[파일이동 실패 - " . $userfile_name[$i] . "] ".dirname($userfile)." 디렉토리가 존재하지 않습니다.";
					}	// if()
				}	// if()
			}else if ( !is_writable($userfile) )
			{
				$errorMsg .= "\\n\\n[파일이동 실패 - " . $userfile_name[$i] . "] 원본 파일에 이동권한이 없습니다.";
			}else if ( $errorMsgTmp = mkdir_parent($target_dir) )
			{
				$errorMsg .= $errorMsgTmp;
			}else if ( !rename($userfile, $targetfile) )
			{
				$errorMsg .= "\\n\\n[파일이동 실패 - " . $userfile_name[$i] . "] 예기치 못한 오류입니다.";
			}	// if()

			file_debug(__FUNCTION__, $userfile, $targetfile);
		}	// for()

	return $errorMsg;
}



/** File name 보안기능의 확장자 추가 (마침표기준)

*/
function file_name_fix($userfile_name, $userfile_postfix="noexec")
{
	if ($userfile_postfix !== null && trim($userfile_postfix) !== '')
	{
		if ( ! preg_match('/^[a-zA-Z0-9]+$/', $userfile_postfix)) {
			die("Access Denied (key)");
		}

		$name = $userfile_name . "." . $userfile_postfix;
	}else
	{
		$name = $userfile_name;
	}	// if()
	return basename_fix($name);
}	// function()



/** File name 보안기능의 확장자 제거 (마침표기준)

*/
function file_name_unfix($userfile_name, $userfile_postfix="noexec")
{
	if ($userfile_postfix)
	{
		$userfile_name_ext = "." . file_name_ext($userfile_name);
		$name = substr($userfile_name, 0, strlen($userfile_name) - strlen($userfile_name_ext));
	}else
	{
		$name = $userfile_name;
	}	// if()
	return $name;
}	// function()



/** File name 확장자 알아내기 (마침표기준)

*/
function file_name_ext($userfile_name)
{
	$sp_filename = explode(".", $userfile_name);
	$userfile_ext = $sp_filename[sizeof($sp_filename)-1];
	return $userfile_ext;
}



/** File 종류 알아내기 (확장자기준)

*/
function file_kind($userfile_name)
{
	global $UPLOAD;		// file ext list

	$ext = file_name_ext($userfile_name);

	for ($i=0; $i<sizeof($UPLOAD[FILTER_EXT][IMG]); $i++)
	{
		if ( !strcmp(strtoupper($ext), strtoupper($UPLOAD[FILTER_EXT][IMG][$i]) ) )
		{
			return "IMG";
		}	// if()
	}	// for()

	for ($i=0; $i<sizeof($UPLOAD[FILTER_EXT][FLASH]); $i++)
	{
		if ( !strcmp(strtoupper($ext), strtoupper($UPLOAD[FILTER_EXT][FLASH][$i]) ) )
		{
			return "FLASH";
		}	// if()
	}	// for()
}



/** Image 최대크기 제한하기

*/
function file_img_maxsize($img, $maxwidth, $maxheight=FALSE)
{
	if ( file_exists($img) )
	{
		$img_size = getimagesize($img);

		if ($img_size[0] > $maxwidth)
		{
			$size[0] = $maxwidth;
		}else
		{
			$size[0] = $img_size[0];
		}	// if()

		if ( ($img_size[1] > $maxheight) && (is_numeric($maxheight)) )
		{
			$size[1] = $maxheight;
		}else
		{
			$size[1] = $img_size[1];
		}	// if()

		return $size;
	}	// if()
}


/** 부모디렉토리 알아내기

*/
function dir_parent($dir, $depth=1)
{
	$ar_dir = explode("/", $dir);
	$return_dir = "";

	for ($i=1; $i<sizeof($ar_dir) - $depth; $i++)
	{
		$return_dir .= "/" . $ar_dir[$i];
	}	// for()

	return($return_dir);
}


/** 부모 디렉토리까지 한번에 만들기

	linux) mkdir -p DIRECTORY...

*/
function mkdir_parent($dir, $chmod=0707)
{
	global $UPLOAD_ROOT;

	// [2005-07-19] 디렉토리가 존재할때는 생략.
	if (!is_dir($UPLOAD_ROOT . '/' . $dir))
	{
		// 저장할 디렉토리 생성.
		if ( is_writable($UPLOAD_ROOT) )		// 업로드 루트 디렉토리에서 쓰기권한이 있을때만 가능.
		{
			// 2단계이상의 디렉토리 생성하기
			$ex_dir = explode("/", $dir);
			for ($i=0; $i<sizeof($ex_dir); $i++)
			{
				// 단계별 디렉토리명 얻기.  ex) intropage, intropage/data1, intropage/data1/a01
				$ex_dir2 = "";
				for ($j=0; $j<=$i; $j++)
				{
					if ($j > 0) $ex_dir2 .= "/";
					$ex_dir2 .= $ex_dir[$j];
				}
				if ( !is_dir($UPLOAD_ROOT . "/" . $ex_dir2) )
				{
					if ( !mkdir($UPLOAD_ROOT . "/" . $ex_dir2, $chmod) )
					{
						return "\\n\\n[시스템오류]\\n$ex_dir2 디렉토리 만들기가 실패하였습니다.\\n관리자에게 문의하여 주십시오.";
					}

					// root권한이 없는 계정사용자일경우라도 업로드파일이 관리가능토록 모든 권한을 모두에게 허용함.
					chmod($UPLOAD_ROOT . "/" . $ex_dir2, $chmod);

				}	// if()
			}	// for()
		}else{
			return "\\n\\n[시스템오류]\\n업로드 루트 디렉토리에서 쓰기권한이 없습니다.\\n관리자에게 문의하여 주십시오.";
		}	// if()
	}	// if()

	return;		// 만들기 성공.
}


/** 부모 디렉토리까지 한번에 만들기(UPLOAD_ROOT 와 무관함)

	linux) mkdir -p DIRECTORY...

	[2002-08-02]윈도우환경도 지원함.
	ex)
		// save dir
		if ( (!is_dir($pm_dir)) || (!is_writable($pm_dir)) )
		{
			$error_msg = mkdir_parent_full($pm_dir);
			if ($error_msg) msg("페이지 생성이 실패하였습니다." . $error_msg);
		}	// if()

*/
function mkdir_parent_full($dir, $chmod=0707)
{
	// window
	$dir = stripslashes($dir);
	$dir = str_replace("\\", "/", $dir);

	// 2단계이상의 디렉토리 생성하기
	$ex_dir = explode("/", $dir);
	$ex_dir2 = NULL;

	for ($i=0; $i<sizeof($ex_dir); $i++)
	{
		// 단계별 디렉토리명 얻기.  ex) intropage, intropage/data1, intropage/data1/a01
		if ($i > 0) $ex_dir2 .= "/";
		$ex_dir2 .= $ex_dir[$i];
		if ($ex_dir2 == NULL) continue;
		//echo "<HR>[" . $i . "]" . $ex_dir2;

		if ( !is_dir($ex_dir2) )
		{
			// 디렉토리 생성.
			if ( is_writable(dirname($ex_dir2)) )		// 부모 디렉토리에서 쓰기권한이 있을때만 가능.
			{
				if ( !mkdir($ex_dir2, $chmod) )
				{
					return "\\n\\n[시스템오류]\\n$ex_dir2 디렉토리 만들기가 실패하였습니다.\\n관리자에게 문의하여 주십시오.";
				}	// if()

				// root권한이 없는 계정사용자일경우라도 업로드파일이 관리가능토록 모든 권한을 모두에게 허용함.
				chmod($ex_dir2, $chmod);
			}else{
				return "\\n\\n[시스템오류]\\n" . $ex_dir2 . " 디렉토리에서 쓰기권한이 없습니다.\\n관리자에게 문의하여 주십시오.";
			}	// if()

		}	// if()
	}	// for()


	// 저장할 디렉토리 확인.
	if ( !is_writable($ex_dir2))		// 저장할 디렉토리에서 쓰기권한이 있을때만 가능.
	{
		return "\\n\\n[시스템오류]\\n" . $ex_dir2 . " 디렉토리에서 쓰기권한이 없습니다.\\n관리자에게 문의하여 주십시오.";
	}	// if()

	return;		// 만들기 성공.
}


/** 파일 크기 구하기

*/
function file_size($file_name, $file_key, $upload_dir)
{
	global $UPLOAD_ROOT;
	$file_path = "$UPLOAD_ROOT/$upload_dir/" . file_name_fix($file_name, $file_key);
	if(file_exists($file_path))
		$file_size = number_format(ceil(filesize($file_path) / 1024)) . "KB";
	else
		$file_size = 0 . "KB";
	return $file_size;
}	// function()


/** 파일 다운로드 URL 구하기

*/
function file_down_url($file_name, $file_key, $upload_dir, $subtype=NULL)
{
	global $G_SYS;
	$file_down_url = $G_SYS[URL_ROOT] . "/include/download.php?name=" . urlencode($file_name)  . "&key=$file_key&dir=$upload_dir&subtype=$subtype";
	return $file_down_url;
}	// function()


/** 파일 미리보여주기(이미지, 플래쉬)


	[2002-07-26]풍선도움말을 입력가능하게 수정.

*/
function file_view($file_name, $file_key, $upload_dir, $max_width, $alt="첨부파일 : ", $max_height='', $file_name_real='', $file_down_url='')
{
	global $UPLOAD_ROOT, $G_SYS;

	// [2008-06-11] 실제 파일명과 저장된 파일명이 다를 경우 지원
	if ($file_name_real == '')
		$file_name_real = $file_name;

	if ($file_down_url == '')
		$file_down_url = file_down_url($file_name, $file_key, $upload_dir);

	// [2024-09-02] Windows + UTF-8 환경
	if (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN' && strtoupper($G_SYS[CHARSET]) == 'UTF-8') {
		$file_name = file_name_char_limit(iconv_fix('UTF-8', $file_name, 'CP949'));
	}

	$file_path = "$UPLOAD_ROOT/$upload_dir/" . file_name_fix($file_name, $file_key);
	$file_kind = file_kind($file_name_real);

	if ($max_width == 0)
		$max_width = '';

	if ($max_height == 0)
		$max_height = '';

	switch($file_kind)
	{
		case "IMG":
			$img_maxsize = file_img_maxsize($file_path, $max_width, $max_height);
			$img_width = "";
			if ($img_maxsize[0] > 0)  $img_width = " width='" . $img_maxsize[0] . "'";
			$value = "<img src=\"" . $file_down_url . "\" name=preview_img border=0 alt='" . $alt . e($file_name_real) . "' " . $img_width . ">";
			break;
		case "FLASH":
			/*
			$value = "<object classid='clsid:D27CDB6E-AE6D-11cf-96B8-444553540000' codebase='http://active.macromedia.com/flash2/cabs/swflash.cab#version=4,0,0,0' id=intro2 width=400 height=300>
						<param name=movie value='" . $file_down_url . "'>
						<param name=loop value=false>
						<param name=menu value=false>
						<param name=quality value=high>
						<param name=scale value=exactfit>
						<param name=salign value=T>
						<param name=devicefont value=true>
						<embed src='" . $file_down_url . "' loop=false menu=false quality=high scale=exactfit salign=T devicefont=true bgcolor=#FFFFFF width='400' height='300' type='application/x-shockwave-flash' pluginspage='http://www.macromedia.com/shockwave/download/index.cgi?P1_Prod_Version=ShockwaveFlash'>
						</embed>
					</object>";
			*/
			$value = '<script>flashView("'.$file_down_url.'","'.$max_width.'","'.$max_height.'","'.$file_key.'","transparent");</script>';
			break;

	} // switch()

	return $value;
}	// function()



/**
	파일 읽기

	[2002-05-24]
*/
function file_read($file)
{
	// file()함수의 경우 new line 처리가 제대로 되지 않음.
	if (!file_exists($file)) echo("<hr><font color='red'>존재하지 않는 파일입니다.<br>=> $file</font><hr>");
	$fp = fopen($file, "r");
	$return = fread($fp, filesize($file));
	fclose($fp);

	return $return;
}	// function()


/**
	파일 쓰기
		: 파일쓰기가 성공했을때 파일포인터값 반환

	[2002-06-27]
	ex) $return = file_write($dir . "/" . $file, $_js);
*/
function file_write($file, $content, $mode=0777)
{
	global $CHMOD_CHANGE;

	$dir = dirname($file);
	if (!is_dir($dir))
	{
		$error_msg = mkdir_parent_full($dir);
		if ($error_msg)
			error("파일 쓰기 실패 : " . $error_msg, 'FILE', false);
	}	// if()

	$fp = fopen($file, "w");
	// [2005-08-17]폼으로 넘겨받지않은 데이타에서는 불필요함.
	//$content = stripslashes($content);
	$return = fwrite($fp, $content);
	fclose($fp);

	// [2009-04-04] 퍼미션을 지정할 수 있도록 함.
	if ($mode !== NULL)
		@chmod($file, $mode);		// apache 계정일때만 변경됨.

	file_debug(__FUNCTION__, $file);

	return $return;
}	// function()



/**
	파일명이나 경로에 상위 디렉토리로 접근하는지 검사.

	ex)
		if (dir_parent_limit($file))
			die("상위 디렉토리로는 접근하실 수 없습니다.");

*/
function dir_parent_limit($file)
{
	// 상위 디렉토리로 접근하는 문자열이 있을때
	if (strpos(str_replace('\\', '', $file), '../') !== FALSE)
		return true;
	else
		return false;
}	// function()


// [2008-01-24] 업로드된 파일경로에서 디렉토리와 파일명 분리.
// addslashes 된 상태로 간주하고 처리함.
function upload_path_parse($path)
{
	$dir = '';
	$dirs = array();
	if (strpos($path, "\\\\") === false)
	{
		$file = $path;
	} else
	{
		$ex = explode("\\\\", $path);
		for ($i=0; $i<sizeof($ex); $i++)
		{
			if ($i+1 < sizeof($ex))
			{
				$dirs[] = $ex[$i];
			} else
			{
				$file = $ex[$i];
			}	// if()
		}	// for()
		$dir = implode("\\\\", $dirs);
	}	// if()

	return array('dir'=>$dir, 'dirs'=>$dirs, 'file'=>$file);
}	// function()


// [2008-02-26] 업로드 실패 원인을 정확하게 알려줌.
function file_upload_error_msg($file, $size, $max_size)
{
	#msg($file['name'].', '.$file['size'].', '.$file['error'].', '.$size.', '.$max_size, 0);
	#errorlog($file['name'].', '.$file['size'].', '.$file['error'].', '.$size.', '.$max_size, 'DEBUG');
	$msg = '';
	if ($file['error'] !== UPLOAD_ERR_OK)
	{
		switch ($file['error'])
		{
			case UPLOAD_ERR_INI_SIZE:		// 1
				$msg = "업로드하려는 파일크기보다 PHP upload_max_filesize 값이 작습니다.\\n\\n서버관리자에게 문의하여 주시기 바랍니다.";
				break;

			case UPLOAD_ERR_FORM_SIZE:		// 2
				$msg = "제한 용량인 [" . filesize_human($max_size) . "]를 초과하였습니다.";
				break;

			case UPLOAD_ERR_PARTIAL:		// 3
				$msg = "파일 전송이 중간에 실패하였습니다.\\n\\n잠시후 다시 시도하여 주시기 바랍니다.";
				break;

			case UPLOAD_ERR_NO_FILE:		// 4
				$msg = "전송된 파일이 없습니다.\\n\\n서버관리자에게 문의하여 주시기 바랍니다.";
				break;

			default:
				// [2012-11-09] 업로드 실패시 에러 코드 출력
				//$msg = "업로드하려는 파일크기보다 PHP post_max_size 값이 작을 가능성이 있습니다.\\n\\n서버관리자에게 문의하여 주시기 바랍니다.";
				$msg = "업로드하려는 파일크기보다 PHP post_max_size 값이 작을 가능성이 있습니다.(에러코드 : ".$file['error'].")\\n\\n서버관리자에게 문의하여 주시기 바랍니다.";
				break;
		}	// switch()
	}	// if()

	if ($msg == '' && $size > $max_size)
		$msg = "제한 용량인 [" . filesize_human($max_size) . "]를 초과하였습니다.";

	return $msg;
}	// function()


// [2008-02-27] 윈도우에서 지원하지 않는 문자는 파일명에서 자동 치환하기
function file_name_char_limit($name)
{
	// [2008-02-28] 폴더구분에 사용되는 \는 처리하지 않도록 함.
	// [2008-05-30] \t 제외
	//return str_replace(array('\\\\', '/', ':', '*', '?', '"', '<', '>', '|'), '-', $name);
	//return str_replace(array('/', ':', '*', '?', '"', '<', '>', '|'), '-', $name);
	return str_replace(array('/', ':', '*', '?', '"', '<', '>', '|', "\t"), '', $name);
}	// function()

/**
 * 새 탭 열기가 지원되는 확장자 여부
 *   - PDF, 이미지는 다운받지 않고, 새 탭에서 열어 브라우저에서 바로 보여주기시 사용
 *   - html : XSS 공격 가능성을 고려하여 제외
 *   - txt : 브라우저에서 한글이 깨져 보이는 경우 있어 제외
 *
 * @param string $name
 *
 * @return bool
 */
function file_is_new_open_ext($name)
{
	$attach_ext = strtolower(file_name_ext($name));

	return in_array($attach_ext, array('pdf', 'png', 'jpg', 'gif', 'svg'), true);
}

/**
 * 파일 처리 디버깅
 *   - 로컬 개발 환경에서만 표시
 *
 * @param string      $function
 * @param string      $source
 * @param string|null $target
 */
function file_debug($function, $source, $target = null)
{
	if (is_local()) {
		$message = $function . ' : ' . $source;

		if ($target !== null) {
			$message .= ' -> ' . $target;
		}

		$GLOBALS['__NMAIL_DEBUG_CONSOLE_LOG'] .= '<script>console.warn('
			. json_encode(
				$message,
				version_compare(PHP_VERSION, '5.4.0', '>=')
					? JSON_UNESCAPED_UNICODE
					: null
			)
			. ');</script>' . PHP_EOL;
	}
}
