# [メタ情報] # 識別子: マイライブラリXserverのrdphp_exe # システム名: マイライブラリXserverのrd.php # 技術種別: Misc # 機能名: Misc # 使用言語: php # 状態: 実行用 # [/メタ情報] 要約: このPHPスクリプト`rd.php`は、指定されたIDに基づき、メディアファイルの配信URLを動的に決定し、ユーザーを適切なコンテンツへ導く役割を担います。主な機能は以下の通りです。 1. **データ参照の厳格化**: `dropbox_wp_library.json`を本命データソースとして参照し、予備ファイル読み込みは廃止。JSONが存在しない場合はエラー。 2. **ID検索とURL選択**: * リクエストIDがS列(低画質ID)に一致した場合、無条件でBunnyCDNの低画質URLへリダイレクトします。 * リクエストIDがB列(通常ID)に一致した場合、JSON内の設定(`column_M`または`select_no`)に基づき、Dropbox、BunnyCDN(高画質)、Xserver、pCloudのいずれかのサーバーから最適なURLを選択します。 3. **エラー処理**: JSONファイルの読み込み失敗、IDの不一致、ターゲットURLが空の場合など、各段階で詳細なエラーメッセージを出力し処理を停止します。 4. **コンテンツ配信**: * `.txt`, `.vtt`, `.srt` などのテキストファイルは、リモートから取得してUTF-8に変換後、直接ブラウザに出力します。 * それ以外のファイルは、URLに`?v=`パラメータ(特定サーバーでは省略)を付与し、HTTP 302リダイレクトを行います。 5. **キャッシュ抑止**: 全てのレスポンスでキャッシュを無効化します。 これにより、コンテンツの柔軟な配信と厳格なエラー管理を実現します。 Xserver WordPressサーバー rd.php /XXXXXX.com/public_html/ ``` 無条件で低画質URL (bn_low_url) へ // - 2. B列 (wpidex) にヒットし、再生選択が 2 の場合 -> 高画質URL (bn_high_url) へ // - 3. 予備ファイルの読み込みを廃止し、本命JSONのみを厳格に参照する仕様に変更 // =============================================================================== // 共通: キャッシュ抑止 header("Cache-Control: no-store, no-cache, must-revalidate, max-age=0"); header("Pragma: no-cache"); header("Expires: 0"); // 🟢 本命のパス1つだけを厳格に指定(予備の配列は廃止) const JSON_PATH = '/home/XXXXXX/XXXXXX.com/public_html/_secure/wp_json/dropbox_wp_library.json'; const PCLOUD_JSON_PATH = '/home/XXXXXX/XXXXXX.com/public_html/_secure/wp_json/pcloud_library.json'; $id = isset($_GET['id']) ? trim($_GET['id']) : ''; $diag = isset($_GET['diag']) ? (int)$_GET['diag'] : 0; if ($diag) header("Content-Type: text/plain; charset=UTF-8"); if ($id === '') { die("Error 400: ID parameter is missing."); } // id 正規化(拡張子除去版) $extlist = 'mp4|mov|jpg|jpeg|png|gif|txt|vtt|srt'; $id_norm = preg_replace('/\.(' . $extlist . ')$/i', '', $id); // 🟢 JSONが存在しない場合は、ここで即座にエラーを出して止まる if (!file_exists(JSON_PATH)) { die("Error 500: Fatal Error - Main JSON file is missing at " . JSON_PATH); } $json_raw = @file_get_contents(JSON_PATH); if ($json_raw === false || $json_raw === '') { die("Error 500: Main JSON file is empty or unreadable."); } // 以降の処理(vパラメータ等)のために変数名を揃える $json_path_used = JSON_PATH; $data = json_decode($json_raw, true); if (!is_array($data)) { die("Error 500: JSON decode failed."); } // JSONのキーに全角スペース等が混ざっていても元データを破壊せず安全に取り出す関数 function get_json_val($item, $target_key) { if (isset($item[$target_key])) return $item[$target_key]; foreach ($item as $k => $v) { $clean_k = trim(preg_replace('/[\s ]+/u', '', $k)); if ($clean_k === $target_key) return $v; } return ''; } // ------------------------------------------------------- // 1. 検索ループ(S列照合とB列照合) // ------------------------------------------------------- $target = null; $is_bunny_low_request = false; foreach ($data as $e) { // A. まずS列(低画質ID)に一致するかチェック $s_key = get_json_val($e, 'bn_low_wpidex'); $s_key_norm = preg_replace('/\.(' . $extlist . ')$/i', '', $s_key); if ($s_key_norm !== '' && strcasecmp($id_norm, $s_key_norm) === 0) { $target = $e; $is_bunny_low_request = true; break; } // B. 次にB列(通常ID)に一致するかチェック $b_key = get_json_val($e, 'wpidex'); $b_key_norm = preg_replace('/\.(' . $extlist . ')$/i', '', $b_key); if ($b_key_norm !== '' && strcasecmp($id_norm, $b_key_norm) === 0) { $target = $e; $is_bunny_low_request = false; break; } } // 画面を真っ白にせず、見つからなかったことを通知 if ($target === null) { die("Error 404: Target ID not found in JSON. requested_id={$id}\n(Checked: " . JSON_PATH . ")"); } // ------------------------------------------------------- // 2. サーバー種別の判定 // ------------------------------------------------------- $column_M = get_json_val($target, 'column_M') !== '' ? (int)get_json_val($target, 'column_M') : 0; $select_no = get_json_val($target, 'select_no') !== '' ? (int)get_json_val($target, 'select_no') : 0; $server_type = 0; if ($column_M >= 1 && $column_M <= 4) { $server_type = $column_M; } elseif ($select_no >= 1 && $select_no <= 4) { $server_type = $select_no; } else { $server_type = 1; } // ------------------------------------------------------- // 3. URLの選択 // ------------------------------------------------------- $url = ''; if ($is_bunny_low_request) { // 🟢 S列アクセス: 無条件で低画質(U列)へ $url = get_json_val($target, 'bn_low_url'); $server_type = 2; // vパラメータ判定用にBunny扱い } else { // 通常のwpidexアクセスの場合は、server_typeに従う if ($server_type === 1) { // ① Dropbox $url = get_json_val($target, 'dropboxlink_url'); } elseif ($server_type === 2) { // ② Bunny 高画質 (T列) $url = get_json_val($target, 'bn_high_url'); } elseif ($server_type === 3) { // ③ Xserver (E列) $url = get_json_val($target, 'wp_encoded_url'); } elseif ($server_type === 4) { // ④ pCloud $pcloud_direct = loadPcloudDirectUrl(get_json_val($target, 'wpidex')); if ($pcloud_direct) { $url = $pcloud_direct; } else { $url = generatePcloudUrl(get_json_val($target, 'wp_pathlink_url')); } } } // フォールバックを廃止し、真っ白ではなくエラー内容を表示させる if (!$url) { die("Error 500: Target URL is empty. server_type={$server_type}, is_low_req=" . ($is_bunny_low_request ? 1 : 0) . ", requested_id={$id}"); } // ------------------------------------------------------- // 4. 以降、共通処理(パラメータ付与、テキストプロキシなど) // ------------------------------------------------------- $path_only = (string)parse_url($url, PHP_URL_PATH); $ext = strtolower(pathinfo($path_only, PATHINFO_EXTENSION)); // Bunny CDN や pCloud の場合は不要な ?v= パラメータを付けない $is_no_v_param = ($server_type === 4) || ($server_type === 2) || (strpos($url, 'https://filedn.eu/') === 0); // v パラメータ $base_ver = (int)@filemtime($json_path_used); $path_crc = sprintf('%u', crc32($path_only)); $path_tail3 = substr($path_crc, -3); $ver = (string)$base_ver . (string)$server_type . (string)$path_tail3; $url_with_v = $is_no_v_param ? $url : addOrReplaceQueryVar($url, 'v', $ver); // ───────────────────────── テキスト系は中継出力 ───────────────────────── if (in_array($ext, ['txt', 'vtt', 'srt'], true)) { $raw = fetchRemote($url_with_v); if ($raw === null) { die("Error 502: Failed to fetch text file from remote."); } $enc = mb_detect_encoding($raw, ['UTF-8', 'SJIS-win', 'CP932', 'SJIS', 'EUC-JP', 'ISO-2022-JP', 'ASCII'], true); if ($enc && strtoupper($enc) !== 'UTF-8') { $raw = mb_convert_encoding($raw, 'UTF-8', $enc); } $raw = preg_replace("/\r\n|\r/u", "\n", $raw); $ctype = ($ext === 'vtt') ? 'text/vtt' : 'text/plain'; header("Content-Type: {$ctype}; charset=UTF-8"); header("X-Content-Type-Options: nosniff"); $fname = basename($path_only); if ($fname === '') $fname = ($id_norm !== '' ? $id_norm : 'file') . '.' . $ext; header('Content-Disposition: inline; filename="' . $fname . '"'); while (ob_get_level()) { ob_end_clean(); } echo $raw; exit; } // ───────────────────────── それ以外はリダイレクト ───────────────────────── if ($diag) { echo "id(raw): {$id}\n"; echo "id(norm): {$id_norm}\n"; echo "is_low_req: " . ($is_bunny_low_request ? '1' : '0') . "\n"; echo "server_type: {$server_type}\n"; echo "url(base): {$url}\n"; echo "url_with_v: {$url_with_v}\n"; echo "OK\n"; exit; } header("Location: " . $url_with_v, true, 302); exit; // ====================================================================== // Helper Functions // ====================================================================== function loadPcloudDirectUrl($wpidex) { $wpidex = (string)$wpidex; if ($wpidex === '') return null; static $cache = null; if ($cache === null) { if (!is_readable(PCLOUD_JSON_PATH)) return null; $raw = @file_get_contents(PCLOUD_JSON_PATH); if (!$raw) return null; $arr = json_decode($raw, true); if (!is_array($arr)) return null; $map = []; foreach ($arr as $row) { if (!isset($row['wpidex'], $row['direct_url'])) continue; $map[(string)$row['wpidex']] = trim((string)$row['direct_url']); } $cache = $map; } return $cache[$wpidex] ?? null; } function generatePcloudUrl($original_url) { $prefix = "https://XXXXXX.com/wp-content/"; $pcloud_base = "https://filedn.eu/[pCloudの固有ID]/"; if (strpos($original_url, $prefix) === 0) return $pcloud_base . substr($original_url, strlen($prefix)); return ''; } function addOrReplaceQueryVar($url, $key, $value) { $p = parse_url($url); $query = []; if (!empty($p['query'])) parse_str($p['query'], $query); $query[$key] = $value; $scheme = isset($p['scheme']) ? $p['scheme']. '://' : ''; $host = $p['host'] ?? ''; $port = isset($p['port']) ? ':' . $p['port'] : ''; $path = $p['path'] ?? ''; return $scheme . $host . $port . $path . '?' . http_build_query($query) . (isset($p['fragment']) ? '#' . $p['fragment'] : ''); } function fetchRemote($url) { if (function_exists('curl_init')) { $ch = curl_init($url); curl_setopt_array($ch, [ CURLOPT_RETURNTRANSFER => true, CURLOPT_FOLLOWLOCATION => true, CURLOPT_MAXREDIRS => 5, CURLOPT_TIMEOUT => 15, CURLOPT_USERAGENT => 'XXXXXX-rd-php/1.0', ]); $data = curl_exec($ch); $code = curl_getinfo($ch, CURLINFO_RESPONSE_CODE); curl_close($ch); return ($data !== false && $code >= 200 && $code < 400) ? $data : null; } return @file_get_contents($url); } ?> ```