From 3a4612420c847096797cfbadde29afcf1f29865d Mon Sep 17 00:00:00 2001 From: thisgun Date: Mon, 8 Jun 2026 02:09:17 +0000 Subject: [PATCH] Improve installer validation and error handling --- install/ajax.install.check.php | 33 +-- install/index.php | 2 + install/install.function.php | 396 ++++++++++++++++++++++++++++++++- install/install_config.php | 73 +++++- install/install_db.php | 324 ++++++++++++++------------- install/library.check.php | 76 ++++++- 6 files changed, 731 insertions(+), 173 deletions(-) diff --git a/install/ajax.install.check.php b/install/ajax.install.check.php index 0730994f7..c7d48aa28 100644 --- a/install/ajax.install.check.php +++ b/install/ajax.install.check.php @@ -7,6 +7,8 @@ include_once('../lib/common.lib.php'); // 공통 라이브러리 include_once('../lib/hook.lib.php'); // hook 함수 파일 include_once('../lib/get_data.lib.php'); // 데이터 가져오는 함수 모음 +@header('Content-Type: application/json; charset=utf-8'); + $data_path = '../'.G5_DATA_DIR; // 파일이 존재한다면 설치할 수 없다. @@ -30,29 +32,32 @@ $ajax_token = md5($tmp_str.$_SERVER['REMOTE_ADDR'].dirname(dirname(__FILE__).'/' $bool_ajax_token = (isset($_POST['ajax_token']) && ($ajax_token == $_POST['ajax_token'])) ? true : false; -if (!($mysql_host && $mysql_user && $mysql_pass && $mysql_db && $table_prefix && $bool_ajax_token)) { +if (!($mysql_host && $mysql_user && $mysql_db && $table_prefix && $bool_ajax_token)) { die(install_json_msg('잘못된 요청입니다.')); } -try { - $dblink = sql_connect($mysql_host, $mysql_user, $mysql_pass, $mysql_db); -} catch (Exception $e) { +$connect = install_db_connect($mysql_host, $mysql_user, $mysql_pass, $mysql_db); +$dblink = $connect['link']; + +if (!$dblink || $connect['message']) { + if ($connect['error']) { + install_error_log($connect['message'].' | '.$connect['error']); + } + die(install_json_msg($connect['message'] ? $connect['message'] : 'MySQL 정보를 확인해 주십시오.')); } -if (!isset($dblink)) { - die(install_json_msg('MySQL Host, User, Password 를 확인해 주십시오.')); +$db_check = install_check_db_capability($dblink, $table_prefix); +if (!$db_check[0]) { + die(install_json_msg($db_check[1])); } -try { - $select_db = sql_select_db($mysql_db, $dblink); -} catch (Exception $e) { +$table_check_error = ''; +$table_exists = install_table_exists($dblink, $table_prefix.'config', $table_check_error); +if ($table_check_error) { + die(install_json_msg('테이블 존재 여부를 확인하지 못했습니다. DB 계정 권한을 확인해 주십시오.')); } -if (!isset($select_db)) { - die(install_json_msg('MySQL DB 를 확인해 주십시오.')); -} - -if (sql_query("SHOW TABLES LIKE `{$table_prefix}config`", G5_DISPLAY_SQL_ERROR, $dblink)) { +if ($table_exists) { die(install_json_msg('주의! 이미 테이블이 존재하므로, 기존 DB 자료가 망실됩니다. 계속 진행하겠습니까?', 'exists')); } diff --git a/install/index.php b/install/index.php index c2d6721e9..a7e3a3c16 100644 --- a/install/index.php +++ b/install/index.php @@ -12,6 +12,7 @@ include_once ('./install.inc.php'); if ($exists_data_dir && $write_data_dir) { // 필수 모듈 체크 require_once('./library.check.php'); + if (empty($install_library_required_missing)) { ?>
@@ -48,6 +49,7 @@ function frm_submit(f) } diff --git a/install/install.function.php b/install/install.function.php index 775d8b6a7..c66ff8bde 100644 --- a/install/install.function.php +++ b/install/install.function.php @@ -56,4 +56,398 @@ if( ! function_exists('install_json_msg') ){ return json_encode(array('error'=>$error_msg, 'success'=>$success_msg, 'exists'=>$exists_msg)); } -} \ No newline at end of file +} + +if( ! function_exists('install_error_log') ){ + function install_error_log($message) { + $err_file = isset($_SERVER['SCRIPT_NAME']) ? $_SERVER['SCRIPT_NAME'] : ''; + @error_log('[g5 install] '.$message.' | file: '.$err_file); + } +} + +if( ! function_exists('install_html_escape') ){ + function install_html_escape($str) { + return htmlspecialchars((string) $str, ENT_QUOTES, 'UTF-8'); + } +} + +if( ! function_exists('install_db_error') ){ + function install_db_error($link=null) { + if (function_exists('mysqli_connect') && G5_MYSQLI_USE) { + if ($link) { + return mysqli_errno($link).' : '.mysqli_error($link); + } + return mysqli_connect_errno().' : '.mysqli_connect_error(); + } + + if (function_exists('mysql_error')) { + return $link ? mysql_errno($link).' : '.mysql_error($link) : mysql_errno().' : '.mysql_error(); + } + + return ''; + } +} + +if( ! function_exists('install_db_query') ){ + function install_db_query($sql, $link) { + if (function_exists('mysqli_query') && G5_MYSQLI_USE) { + return @mysqli_query($link, $sql); + } + + return @mysql_query($sql, $link); + } +} + +if( ! function_exists('install_db_fetch_row') ){ + function install_db_fetch_row($result) { + if (!$result) { + return false; + } + + if (function_exists('mysqli_fetch_row') && G5_MYSQLI_USE) { + return mysqli_fetch_row($result); + } + + return mysql_fetch_row($result); + } +} + +if( ! function_exists('install_db_num_rows') ){ + function install_db_num_rows($result) { + if (!$result) { + return 0; + } + + if (function_exists('mysqli_num_rows') && G5_MYSQLI_USE) { + return mysqli_num_rows($result); + } + + return mysql_num_rows($result); + } +} + +if( ! function_exists('install_db_connect') ){ + function install_db_connect($host, $user, $pass, $db) { + $result = array('link'=>false, 'error'=>'', 'message'=>''); + + if (function_exists('mysqli_connect') && G5_MYSQLI_USE) { + if (function_exists('mysqli_report')) { + mysqli_report(MYSQLI_REPORT_OFF); + } + + $link = @mysqli_connect($host, $user, $pass); + if (!$link) { + $result['error'] = install_db_error(); + $result['message'] = 'MySQL Host, User, Password 정보를 확인해 주십시오.'; + return $result; + } + + if (!@mysqli_select_db($link, $db)) { + $result['link'] = $link; + $result['error'] = install_db_error($link); + $result['message'] = 'MySQL DB 정보를 확인해 주십시오.'; + return $result; + } + + $result['link'] = $link; + return $result; + } + + if (!function_exists('mysql_connect')) { + $result['message'] = 'MySQL 확장(mysqli/mysql)이 설치되어 있지 않습니다.'; + return $result; + } + + $link = @mysql_connect($host, $user, $pass); + if (!$link) { + $result['error'] = install_db_error(); + $result['message'] = 'MySQL Host, User, Password 정보를 확인해 주십시오.'; + return $result; + } + + if (!@mysql_select_db($db, $link)) { + $result['link'] = $link; + $result['error'] = install_db_error($link); + $result['message'] = 'MySQL DB 정보를 확인해 주십시오.'; + return $result; + } + + $result['link'] = $link; + return $result; + } +} + +if( ! function_exists('install_sql_like_escape') ){ + function install_sql_like_escape($str) { + return str_replace(array('\\', '%', '_'), array('\\\\', '\%', '\_'), $str); + } +} + +if( ! function_exists('install_sql_escape') ){ + function install_sql_escape($str, $link) { + if (function_exists('mysqli_real_escape_string') && G5_MYSQLI_USE) { + return mysqli_real_escape_string($link, $str); + } + + return mysql_real_escape_string($str, $link); + } +} + +if( ! function_exists('install_table_exists') ){ + function install_table_exists($link, $table, &$error='') { + $error = ''; + $table_like = install_sql_escape(install_sql_like_escape($table), $link); + $result = install_db_query("SHOW TABLES LIKE '{$table_like}'", $link); + + if (!$result) { + $error = install_db_error($link); + install_error_log('table exists check failed: '.$error.' | table: '.$table); + return false; + } + + return install_db_num_rows($result) > 0; + } +} + +if( ! function_exists('install_get_existing_tables') ){ + function install_get_existing_tables($link, $prefixes) { + $tables = array(); + + foreach ($prefixes as $prefix) { + if (!$prefix) { + continue; + } + + $table_like = install_sql_escape(install_sql_like_escape($prefix).'%', $link); + $result = install_db_query("SHOW TABLES LIKE '{$table_like}'", $link); + + while ($row = install_db_fetch_row($result)) { + if (isset($row[0])) { + $tables[$row[0]] = $row[0]; + } + } + } + + ksort($tables); + + return array_values($tables); + } +} + +if( ! function_exists('install_fail_page') ){ + function install_fail_page($message, $link=null, $prefixes=array()) { + global $install_progress_started; + + install_error_log($message); + + if (!empty($install_progress_started)) { + $install_progress_started = false; +?> + + + +
+

설치를 계속할 수 없습니다.

+

+ +

설치가 중간에 멈춘 경우 아래 테이블이 일부 생성되었을 수 있습니다. 다시 설치하려면 DB에서 해당 테이블을 정리하거나, 재설치 옵션을 선택한 뒤 진행해 주십시오.

+
    + +
  • + +
+ + +
+ '.PHP_EOL; -} \ No newline at end of file +$install_library_required_missing = false; +$install_library_checks = array( + array( + 'name' => 'MySQL 확장', + 'required' => true, + 'ok' => (function_exists('mysqli_connect') && G5_MYSQLI_USE) || function_exists('mysql_connect'), + 'message' => 'MySQL DB 연결에 필요합니다.' + ), + array( + 'name' => 'JSON', + 'required' => true, + 'ok' => function_exists('json_encode') && function_exists('json_decode'), + 'message' => '설치 전 DB 점검 응답 처리에 필요합니다.' + ), + array( + 'name' => 'iconv 또는 mbstring', + 'required' => true, + 'ok' => function_exists('iconv') || function_exists('mb_convert_encoding'), + 'message' => '문자열 인코딩 처리에 필요합니다.' + ), + array( + 'name' => 'GD', + 'required' => false, + 'ok' => extension_loaded('gd') && function_exists('gd_info'), + 'message' => '자동등록방지 문자와 썸네일 기능에 필요합니다.' + ), + array( + 'name' => 'OpenSSL', + 'required' => false, + 'ok' => extension_loaded('openssl'), + 'message' => '암호화, 외부 연동, 보안 통신 기능 사용 시 권장됩니다.' + ), + array( + 'name' => 'cURL', + 'required' => false, + 'ok' => function_exists('curl_init'), + 'message' => '외부 API, 결제, 소셜 연동 사용 시 권장됩니다.' + ), + array( + 'name' => 'Fileinfo', + 'required' => false, + 'ok' => function_exists('finfo_open'), + 'message' => '업로드 파일의 MIME 타입 확인에 권장됩니다.' + ) +); + +foreach ($install_library_checks as $check) { + if ($check['required'] && !$check['ok']) { + $install_library_required_missing = true; + break; + } +} +?> +
+

서버 환경 점검

+
    + +
  • + + - + () + : +
  • + +
+ +

필수 서버 환경이 준비되지 않아 설치를 진행할 수 없습니다. 누락된 PHP 확장을 설치한 뒤 새로고침해 주십시오.

+ +

필수 서버 환경을 확인했습니다. 권장 항목은 설치 후 일부 기능 사용에 영향을 줄 수 있습니다.

+ +