filter_var($domain, FILTER_SANITIZE_URL), "key" => filter_var($key, FILTER_SANITIZE_STRING), "user_ip" => filter_var($ip, FILTER_VALIDATE_IP) ? $ip : '0.0.0.0', "g5_table_prefix" => defined("G5_TABLE_PREFIX") ? G5_TABLE_PREFIX : "g5_", "g5_shop_table_prefix" => defined("G5_SHOP_TABLE_PREFIX") ? G5_SHOP_TABLE_PREFIX : "g5_shop_" ); $ch = curl_init(); curl_setopt_array($ch, [ CURLOPT_URL => $api_endpoint, CURLOPT_POST => true, CURLOPT_POSTFIELDS => http_build_query($post_data), CURLOPT_USERAGENT => "Mozilla/5.0 (rebuilder.co.kr)", CURLOPT_RETURNTRANSFER => true, CURLOPT_FOLLOWLOCATION => true, CURLOPT_SSL_VERIFYHOST => 0, CURLOPT_SSL_VERIFYPEER => 0, CURLOPT_TIMEOUT => 30 ]); $response = curl_exec($ch); if (curl_errno($ch)) { $error_msg = curl_error($ch); curl_close($ch); return "업데이트 서버 연결 에러: " . $error_msg; } curl_close($ch); if ($response === false) { return "업데이트 서버로부터 응답이 없습니다."; } $response = preg_replace('/^\xEF\xBB\xBF/', '', $response); // UTF-8 BOM 제거 $data = json_decode($response, true); if (json_last_error() !== JSON_ERROR_NONE) { return "업데이트 서버의 응답을 처리할 수 없습니다. (JSON 오류)"; } if (isset($data["status"]) && $data["status"] === "error") { return "업데이트 서버 응답: " . htmlspecialchars($data["data"]); } // 💡 [수정] 스키마 정보가 없어도 오류로 처리하지 않고, 로컬 강제 업데이트를 위해 빈 배열을 반환하도록 수정 if (empty($data["data"]["schema"]["tables"])) { $data["data"]["schema"]["tables"] = []; } return $data; } /** * DB 구조를 업그레이드하는 함수 * @param array $schema DB 스키마 정보 * @return string 결과 메시지 */ function upgrade_database($schema) { $is_upgrade = false; $messages = []; if (!empty($schema["tables"])) { foreach ($schema["tables"] as $table_name => $info) { $columns = $info["columns"]; $table_name = sql_real_escape_string($table_name); $result = sql_query("SHOW TABLES LIKE '{$table_name}'"); if (mysqli_num_rows($result) == 0) { // 테이블이 없으면 새로 생성 $column_defs = []; foreach ($columns as $col => $def) { $column_defs[] = "`" . sql_real_escape_string($col) . "` " . sql_real_escape_string($def); } if (isset($info["primary_key"])) { $column_defs[] = "PRIMARY KEY (`" . sql_real_escape_string($info["primary_key"]) . "`)"; } $create_sql = "CREATE TABLE `{$table_name}` (" . implode(", ", $column_defs) . ") ENGINE=MyISAM DEFAULT CHARSET=utf8"; if (sql_query($create_sql)) { $messages[] = "[{$table_name}] 테이블을 성공적으로 생성했습니다."; $is_upgrade = true; } else { return "[{$table_name}] 테이블 생성 실패: " . mysqli_error($GLOBALS["g5"]["connect_db"]); } } else { // 테이블이 있으면 컬럼 확인 후 추가 $add_columns = []; foreach ($columns as $col => $def) { $col = sql_real_escape_string($col); $col_exists = sql_query("SHOW COLUMNS FROM `{$table_name}` LIKE '{$col}'"); if (mysqli_num_rows($col_exists) == 0) { $add_columns[] = "ADD `" . $col . "` " . sql_real_escape_string($def); } } if (!empty($add_columns)) { $alter_sql = "ALTER TABLE `{$table_name}` " . implode(", ", $add_columns); if (sql_query($alter_sql)) { $messages[] = "[{$table_name}] 테이블에 새로운 컬럼을 추가했습니다."; $is_upgrade = true; } else { return "[{$table_name}] 컬럼 추가 실패: " . mysqli_error($GLOBALS["g5"]["connect_db"]); } } } } } if ($is_upgrade) { return implode("
", $messages); } else { return "공식 DB 업데이트 내역이 없습니다."; } } /** * 💡 [핵심 기능 추가] 커스텀 모듈용 컬럼을 강제로 확인하고 추가하는 함수 * @return array [ 'is_upgrade' => (bool), 'messages' => (array) ] */ function add_missing_custom_columns() { $is_upgrade = false; $messages = []; $tables_to_check = ['rb_module', 'rb_module_shop']; $column_to_add = 'md_custom_skin'; $column_definition = "VARCHAR(255) NOT NULL DEFAULT '' COMMENT '커스텀 모듈 스킨' AFTER `md_poll_id`"; foreach ($tables_to_check as $table) { // 테이블이 존재하는지 먼저 확인 if (sql_query("DESCRIBE {$table}", false)) { // 컬럼이 존재하는지 확인 $col_exists = sql_query("SHOW COLUMNS FROM `{$table}` LIKE '{$column_to_add}'"); if (mysqli_num_rows($col_exists) == 0) { // 컬럼이 없으면 추가 $alter_sql = "ALTER TABLE `{$table}` ADD `{$column_to_add}` {$column_definition}"; if (sql_query($alter_sql)) { $messages[] = "[{$table}] 테이블에 `{$column_to_add}` 컬럼을 성공적으로 추가했습니다."; $is_upgrade = true; } else { $messages[] = "[{$table}] 테이블에 `{$column_to_add}` 컬럼 추가 실패: " . mysqli_error($GLOBALS["g5"]["connect_db"]); } } } } return ['is_upgrade' => $is_upgrade, 'messages' => $messages]; } // --- 메인 로직 시작 --- $g5["title"] = "DB 업그레이드"; include_once "../admin.head.php"; $db_upgrade_msg = ''; $final_messages = []; $official_upgrade_done = false; $custom_upgrade_done = false; $license_key = get_license_key(); if (!is_string($license_key)) { $db_upgrade_msg = "라이선스 키를 가져오는 중 오류가 발생했습니다."; } else { $site_domain = $_SERVER["HTTP_HOST"]; $user_ip = get_real_client_ip(); $response_data = verify_license_and_get_schema($license_key, $site_domain, $user_ip); if (is_string($response_data)) { // verify_license_and_get_schema 함수에서 에러 메시지를 반환한 경우 $final_messages[] = $response_data; } else { // 성공적으로 스키마 정보를 받아온 경우, 공식 업데이트 실행 $schema = $response_data["data"]["schema"]; $official_upgrade_result = upgrade_database($schema); $final_messages[] = $official_upgrade_result; if (strpos($official_upgrade_result, '성공적으로') !== false || strpos($official_upgrade_result, '새로운 컬럼을 추가') !== false) { $official_upgrade_done = true; } } // 💡 [핵심] 공식 업데이트 후, 커스텀 컬럼 강제 추가 로직 실행 $custom_upgrade_result = add_missing_custom_columns(); if (!empty($custom_upgrade_result['messages'])) { $final_messages = array_merge($final_messages, $custom_upgrade_result['messages']); } if ($custom_upgrade_result['is_upgrade']) { $custom_upgrade_done = true; } // 최종 결과 메시지 조합 if ($official_upgrade_done || $custom_upgrade_done) { $db_upgrade_msg = implode("
", array_filter($final_messages)) . "

DB 업그레이드가 완료되었습니다."; } else { $db_upgrade_msg = "더 이상 업그레이드 할 내용이 없습니다.
현재 DB는 최신 상태입니다."; } } ?>