first commit 2

This commit is contained in:
hmw1001
2026-06-11 18:47:38 +09:00
parent c768729ce6
commit 6f534e33a6
11095 changed files with 1595758 additions and 0 deletions
+275
View File
@@ -0,0 +1,275 @@
<?php
// ===================================================================================
// 리빌더 DB 자동 업그레이드
// 이 파일은 리빌더의 데이터베이스 테이블 구조를 최신 상태로 유지합니다.
// ===================================================================================
$sub_menu = "000060";
include_once "./_common.php";
// --- 권한 확인 ---
auth_check_menu($auth, $sub_menu, "w");
if ($is_admin != "super") {
alert("최고관리자만 접근 가능합니다.");
}
/**
* rb_key 테이블이 없으면 생성하고, 키가 없으면 기본 키를 삽입하는 함수
*/
function check_and_create_key_table()
{
// 테이블 존재 여부 확인
if (!sql_query("DESCRIBE rb_key", false)) {
// 테이블 생성
sql_query("CREATE TABLE IF NOT EXISTS `rb_key` (
`key_no` varchar(255) NOT NULL DEFAULT '',
`key_datetime` datetime NOT NULL DEFAULT '0000-00-00 00:00:00'
) ENGINE=MyISAM DEFAULT CHARSET=utf8", true);
}
// 키 존재 여부 확인
$key_count = sql_fetch("SELECT COUNT(*) as cnt FROM rb_key");
if ($key_count['cnt'] < 1) {
// 초기 키 생성 및 삽입
$in_key = get_random_token_string(24);
$in_key = sql_real_escape_string($in_key);
sql_query("INSERT INTO rb_key SET key_no = '{$in_key}', key_datetime = '" . G5_TIME_YMDHIS . "'");
}
}
/**
* DB에서 라이선스 키 정보를 가져오는 함수
* @return array|string 키 정보 배열 또는 에러 메시지
*/
function get_license_key()
{
check_and_create_key_table(); // 테이블 및 키 존재 보장
$key_info = sql_fetch("SELECT key_no FROM rb_key LIMIT 1");
if (!$key_info || empty($key_info["key_no"])) {
return "라이선스 키를 찾을 수 없습니다.";
}
return $key_info["key_no"];
}
/**
* 외부 API 서버에 라이선스를 검증하고 최신 DB 스키마를 받아오는 함수
* @param string $key 라이선스 키
* @param string $domain 사이트 도메인
* @param string $ip 사용자 IP
* @return array|string 성공 시 데이터 배열, 실패 시 에러 메시지
*/
function verify_license_and_get_schema($key, $domain, $ip)
{
if (!function_exists("curl_init")) {
return "cURL을 사용할 수 없는 서버입니다. 서버 관리자에게 문의하세요.";
}
$api_endpoint = "https://api.rebuilder.co.kr/_update.php";
$post_data = array(
"domain" => 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("<br>", $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("<br>", array_filter($final_messages)) . "<br><br><b>DB 업그레이드가 완료되었습니다.</b>";
} else {
$db_upgrade_msg = "더 이상 업그레이드 할 내용이 없습니다.<br>현재 DB는 최신 상태입니다.";
}
}
?>
<!-- 결과 출력 -->
<div class="local_desc01 local_desc">
<p><?php echo $db_upgrade_msg; ?></p>
</div>
<?php
// 테일 포함
include_once "../admin.tail.php";
?>