$value) { if (strpos($name, 'HTTP_') === 0) { $key = str_replace('_', '-', ucwords(strtolower(str_replace('_', ' ', substr($name, 5))))); $headers[$key] = $value; } } return $headers; } } // 兼容 str_starts_with() 函数 if (!function_exists('str_starts_with')) { function str_starts_with($haystack, $needle) { return substr($haystack, 0, strlen($needle)) === $needle; } } // 兼容 str_contains 函数 if (!function_exists('str_contains')) { function str_contains($haystack, $needle) { return $needle !== '' && strpos($haystack, $needle) !== false; } } // 构造请求头 $headers = []; foreach (getallheaders() as $name => $value) { if (strtolower($name) !== 'host') { $headers[] = "$name: $value"; } } $headers[] = "Host: $host"; $headers[] = "User-Agent: AppleCoreMedia/1.0.0.7B367 (iPad; U; CPU OS 4_3_3 like Mac OS X)"; $headers[] = "Referer: https://$host/"; $headers[] = "Accept-Encoding: gzip, deflate"; // 发起请求 $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $request_url); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_HEADER, true); curl_setopt($ch, CURLOPT_FOLLOWLOCATION, false); curl_setopt($ch, CURLOPT_HTTPHEADER, $headers); curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false); curl_setopt($ch, CURLOPT_ENCODING, ""); curl_setopt($ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1); if ($_SERVER['REQUEST_METHOD'] === 'POST') { curl_setopt($ch, CURLOPT_POST, true); curl_setopt($ch, CURLOPT_POSTFIELDS, file_get_contents('php://input')); } $response = curl_exec($ch); $curl_error = curl_error($ch); $http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE); $header_size = curl_getinfo($ch, CURLINFO_HEADER_SIZE); curl_close($ch); // 拆分头和主体 $headers_raw = substr($response, 0, $header_size); $body = substr($response, $header_size); // 解析头 $response_headers = []; foreach (explode("\r\n", $headers_raw) as $line) { if (stripos($line, 'HTTP/') === 0) { $response_headers[] = $line; continue; } $parts = explode(': ', $line, 2); if (count($parts) === 2) { $response_headers[strtolower($parts[0])] = $parts[1]; } } // 重定向处理 if (in_array($http_code, [301, 302, 303, 307, 308]) && isset($response_headers['location'])) { $location = $response_headers['location']; if (!parse_url($location, PHP_URL_SCHEME)) { $base = $parsed_url['scheme'] . '://' . $parsed_url['host']; if (isset($parsed_url['port'])) { $base .= ':' . $parsed_url['port']; } $location = $base . '/' . ltrim($location, '/'); } header("Location: mytv.php?url=" . urlencode($location), true, $http_code); exit(); } // 设置 content-type if (isset($response_headers['content-type'])) { header('Content-Type: ' . $response_headers['content-type']); } // 设置状态码 http_response_code($http_code); // 出错输出 if ($response === false) { die("CURL ERROR: " . $curl_error); } // ========== m3u8 替换逻辑 ========== $is_m3u8 = false; $content_type = $response_headers['content-type'] ?? ''; if ( strpos($request_url, '.m3u8') !== false || stripos($content_type, 'mpegurl') !== false || stripos($content_type, 'application/x-mpegurl') !== false || // stripos($content_type, 'text/plain') !== false || strpos(ltrim($body), '#EXTM3U') === 0 ) { $is_m3u8 = true; } if ($is_m3u8) { $base_root = $parsed_url['scheme'] . '://' . $parsed_url['host'] . (isset($parsed_url['port']) ? ':' . $parsed_url['port'] : ''); $base_dir = $base_root . dirname($parsed_url['path']) . '/'; $body = preg_replace_callback( // 更稳健的正则表达式:匹配 URL、绝对路径、相对路径,允许 query 参数,允许无后缀 '/(?P(https?:\/\/[^\s"\']+)|((\/|\.\.?\/)?[^\s"\']+))/i', function ($matches) use ($base_root, $base_dir) { $url = trim($matches['url']); // 跳过 m3u8 语法行 if (str_starts_with($url, '#')) return $url; // 跳过 data uri 等 if (str_starts_with($url, 'data:')) return $url; // 跳过已经被代理过的 if (str_contains($url, 'mytv.php?url=')) return $url; // 完整 URL if (preg_match('/^https?:\/\//i', $url)) { return 'mytv.php?url=' . urlencode($url); } // 以 / 开头(绝对路径) if (str_starts_with($url, '/')) { return 'mytv.php?url=' . urlencode($base_root . $url); } // 处理 ../ 或 ./ 等相对路径 return 'mytv.php?url=' . urlencode($base_dir . $url); }, $body ); header('Content-Disposition: inline; filename=index.m3u8'); } echo $body; ?>