抓取结果
$latest) { $latest = $time; } } return $latest > 0 ? date('Y-m-d', $latest) : ($fallback !== '' ? $fallback : date('Y-m-d')); } function frontSitemapNewsLastmod($articles, $fallback) { $latest = frontNewsLastmodTimestamp([], $articles); return $latest > 0 ? date('Y-m-d', $latest) : $fallback; } function frontTimestampFromValue($value) { if ($value === '' || $value === null) { return 0; } $time = strtotime((string)$value); return $time ? (int)$time : 0; } function frontLatestTimestamp($values) { $latest = 0; foreach ((array)$values as $value) { $time = is_int($value) ? $value : frontTimestampFromValue($value); if ($time > $latest) { $latest = $time; } } return $latest; } function frontTimestampDate($timestamp, $fallback = '') { $timestamp = (int)$timestamp; if ($timestamp > 0) { return date('Y-m-d', $timestamp); } return $fallback !== '' ? $fallback : date('Y-m-d'); } function frontTemplateLastmodTimestamp($site, $templateFile = '') { $values = [ $site['template_updated_at'] ?? '', $site['updated_at'] ?? '', $site['created_at'] ?? '', ]; if ($templateFile !== '' && is_file($templateFile)) { $values[] = filemtime($templateFile) ?: 0; } return frontLatestTimestamp($values); } function frontNewsLastmodTimestamp($site, $articles = null) { $values = [ is_array($site) ? ($site['news_updated_at'] ?? '') : '', ]; foreach ((array)$articles as $article) { foreach (['updated_at', 'published_at', 'date'] as $key) { $values[] = $article[$key] ?? ''; } } return frontLatestTimestamp($values); } function frontSitemapPanContext($site) { if (($site['generator_version'] ?? '') !== 'v2' || !function_exists('generatedRuntimeCurrentBundle') || !function_exists('generatorPanLoadPlan') || !function_exists('generatorPanLibraryIndexReady')) { return null; } $bundle = generatedRuntimeCurrentBundle($site['id'] ?? ''); $plan = $bundle ? generatorPanLoadPlan($bundle) : null; if (!is_array($plan) || !is_array($bundle)) { return null; } $config = function_exists('generatorConfigFromPlan') ? generatorConfigFromPlan($plan) : []; if (empty($config['generation']['pan_directory_enabled']) || !generatorPanLibraryIndexReady($config, [ 'directory' => $bundle['directory'] ?? $bundle['revision_dir'] ?? '', 'site_dir' => $bundle['site_dir'] ?? '', 'index_directory' => $bundle['site_dir'] ?? '', ])) { return null; } return [ 'bundle' => [ 'directory' => $bundle['directory'] ?? $bundle['revision_dir'] ?? '', 'site_dir' => $bundle['site_dir'] ?? '', 'index_directory' => $bundle['site_dir'] ?? '', ], 'plan' => $plan, 'config' => $config, ]; } function frontOutputSitemap($site, $currentDomain = '', $requestedPath = '/sitemap.xml') { if ($currentDomain !== '') { $site = frontUseRequestHostForCanonical($site, $currentDomain); } $requestedPath = generatedRuntimeNormalizePath($requestedPath ?: '/sitemap.xml'); $panContext = frontSitemapPanContext($site); if ($requestedPath === '/sitemap.xml' && $panContext) { $count = generatorPanLibraryIndexCount($panContext['config'], $panContext['bundle']); $chunkSize = max(1000, min(50000, (int)($panContext['config']['generation']['pan_sitemap_chunk_size'] ?? 20000))); $chunkCount = $count > 0 ? (int)ceil($count / $chunkSize) : 0; header('Content-Type: application/xml; charset=utf-8'); echo "\n"; echo "\n"; echo " " . htmlspecialchars(getCanonicalSiteUrl($site['domain'] ?? '', '/sitemap-static.xml'), ENT_XML1 | ENT_COMPAT, 'UTF-8') . "" . date('Y-m-d') . "\n"; for ($index = 1; $index " . htmlspecialchars(getCanonicalSiteUrl($site['domain'] ?? '', $path), ENT_XML1 | ENT_COMPAT, 'UTF-8') . "" . date('Y-m-d') . "\n"; } echo "\n"; return; } if (preg_match('#^/sitemap-pan-([0-9]+)\.xml$#i', $requestedPath, $match)) { if (!$panContext) { http_response_code(404); header('Content-Type: text/plain; charset=utf-8'); echo "Not found\n"; return; } $page = max(1, (int)$match[1]); $chunkSize = max(1000, min(50000, (int)($panContext['config']['generation']['pan_sitemap_chunk_size'] ?? 20000))); $entries = generatorPanSitemapEntries($panContext['plan'], $panContext['bundle'], $chunkSize, ($page - 1) * $chunkSize); header('Content-Type: application/xml; charset=utf-8'); echo "\n"; echo "\n"; foreach ($entries as $entry) { $path = (string)($entry['url'] ?? ''); if ($path === '') { continue; } echo " " . htmlspecialchars(getCanonicalSiteUrl($site['domain'] ?? '', $path), ENT_XML1 | ENT_COMPAT, 'UTF-8') . "" . htmlspecialchars(frontTimestampDate((int)($entry['lastmod'] ?? 0), date('Y-m-d')), ENT_XML1 | ENT_COMPAT, 'UTF-8') . "monthly0.5\n"; } echo "\n"; return; } $siteId = $site['id'] ?? ''; $templateFile = getTemplateFilePath($siteId); $baseTimestamp = frontTemplateLastmodTimestamp($site, $templateFile); $baseLastmod = frontTimestampDate($baseTimestamp, date('Y-m-d')); $generatedPaths = function_exists('generatedRuntimePaths') ? generatedRuntimePaths($site) : []; $hasGeneratedV2Bundle = ($site['generator_version'] ?? '') === 'v2' && !empty($generatedPaths); // v2 pages are already the canonical generated article set. Do not add // the legacy news storage URLs beside them, or one article gets two // indexable addresses (semantic .html and nYYYY...shtml). $newsArticles = $hasGeneratedV2Bundle ? [] : loadNewsArticles($siteId); $newsTimestamp = frontNewsLastmodTimestamp($site, $newsArticles); $siteLatestTimestamp = max($baseTimestamp, $newsTimestamp); $newsLastmod = frontTimestampDate($siteLatestTimestamp, $baseLastmod); $homeLastmod = frontTimestampDate($siteLatestTimestamp, $baseLastmod); $urls = [ [ 'loc' => getCanonicalSiteUrl($site['domain'] ?? '', '/'), 'lastmod' => $homeLastmod, 'changefreq' => 'weekly', 'priority' => '1.0', ], [ 'loc' => getCanonicalSiteUrl($site['domain'] ?? '', '/news/'), 'lastmod' => $newsLastmod, 'changefreq' => 'daily', 'priority' => '0.8', ], [ 'loc' => getCanonicalSiteUrl($site['domain'] ?? '', '/privacy/'), 'lastmod' => $baseLastmod, 'changefreq' => 'monthly', 'priority' => '0.3', ], [ 'loc' => getCanonicalSiteUrl($site['domain'] ?? '', '/terms/'), 'lastmod' => $baseLastmod, 'changefreq' => 'monthly', 'priority' => '0.3', ], ]; if (!$hasGeneratedV2Bundle) { $totalNewsPages = max(1, (int)ceil(count($newsArticles) / max(1, (int)NEWS_PER_PAGE))); for ($page = 2; $page newsIndexUrl($site, $page), 'lastmod' => $newsLastmod, 'changefreq' => 'daily', 'priority' => '0.7', ]; } foreach ($newsArticles as $article) { $articleTimestamp = frontLatestTimestamp([ $article['updated_at'] ?? '', $article['published_at'] ?? '', $article['date'] ?? '', ]); $urls[] = [ 'loc' => newsArticleUrl($site, $article), 'lastmod' => frontTimestampDate($articleTimestamp, $newsLastmod), 'changefreq' => 'monthly', 'priority' => '0.6', ]; } } foreach ($generatedPaths as $generatedPath) { if (!is_string($generatedPath) || $generatedPath === '' || $generatedPath === '/') { continue; } $urls[] = [ 'loc' => getCanonicalSiteUrl($site['domain'] ?? '', $generatedPath), 'lastmod' => $homeLastmod, 'changefreq' => strpos($generatedPath, '/news/') === 0 ? 'weekly' : 'monthly', 'priority' => $generatedPath === '/news/' ? '0.8' : '0.6', ]; } // Pan-directory URLs are dynamic and therefore do not appear in the // generated bundle manifest. Submit only finite, validated library // articles with a stable category URL; never enumerate synthetic or // unbounded random URLs in the sitemap. if ($requestedPath === '/sitemap.xml' && !$panContext && $hasGeneratedV2Bundle && function_exists('generatedRuntimeCurrentBundle') && function_exists('generatorPanLoadPlan') && function_exists('generatorPanSitemapEntries')) { $bundle = generatedRuntimeCurrentBundle($siteId); $plan = $bundle ? generatorPanLoadPlan($bundle) : null; if (is_array($plan) && is_array($bundle)) { $planConfig = function_exists('generatorConfigFromPlan') ? generatorConfigFromPlan($plan) : []; // An enabled library index is intentionally the only source for // large pan sitemaps. Do not make the first public request scan // thousands of raw files while the background index is missing. $fallbackEntries = empty($planConfig['generation']['pan_library_index_enabled']) ? generatorPanSitemapEntries($plan, ['directory' => $bundle['directory'] ?? ''], 5000) : []; foreach ($fallbackEntries as $entry) { $path = (string)($entry['url'] ?? ''); if ($path === '' || $path === '/') { continue; } $lastmod = frontTimestampDate((int)($entry['lastmod'] ?? 0), $newsLastmod); $urls[] = [ 'loc' => getCanonicalSiteUrl($site['domain'] ?? '', $path), 'lastmod' => $lastmod, 'changefreq' => 'monthly', 'priority' => '0.5', ]; } } } if (function_exists('isGamblingSiteProfile') && isGamblingSiteProfile( $site['title'] ?? '', $site['description'] ?? '', $site['core_keyword'] ?? '', $site['keywords'] ?? '', $site['industry'] ?? '' )) { $urls[] = [ 'loc' => getCanonicalSiteUrl($site['domain'] ?? '', '/responsible-gambling/'), 'lastmod' => $baseLastmod, 'changefreq' => 'monthly', 'priority' => '0.5', ]; } header('Content-Type: application/xml; charset=utf-8'); echo "\n"; echo "\n"; $seenLoc = []; foreach ($urls as $url) { if (($url['loc'] ?? '') === '') { continue; } if (isset($seenLoc[$url['loc']])) { continue; } $seenLoc[$url['loc']] = true; echo " \n"; echo " " . htmlspecialchars($url['loc'], ENT_XML1 | ENT_COMPAT, 'UTF-8') . "\n"; echo " " . htmlspecialchars($url['lastmod'], ENT_XML1 | ENT_COMPAT, 'UTF-8') . "\n"; echo " " . htmlspecialchars($url['changefreq'], ENT_XML1 | ENT_COMPAT, 'UTF-8') . "\n"; echo " " . htmlspecialchars($url['priority'], ENT_XML1 | ENT_COMPAT, 'UTF-8') . "\n"; echo " \n"; } echo "\n"; } function frontLoadNormalizedBrandTemplateHtml($site) { $templateHtml = ''; $templateFile = getTemplateFilePath($site['id'] ?? ''); if ($templateFile !== '' && is_file($templateFile)) { $templateHtml = (string)@file_get_contents($templateFile); } if ($templateHtml !== '' && function_exists('normalizeTemplateBrandNavigation')) { $homeUrl = function_exists('getCanonicalSiteUrl') ? getCanonicalSiteUrl($site['domain'] ?? '', '/') : '/'; if ($homeUrl === '') { $homeUrl = '/'; } $templateHtml = normalizeTemplateBrandNavigation( $templateHtml, $site['title'] ?? '', $site['domain'] ?? '', $homeUrl, $site['core_keyword'] ?? '', $site['language'] ?? 'zh-CN' ); if (function_exists('cleanupTemplateBrandAnchorClosings')) { $templateHtml = cleanupTemplateBrandAnchorClosings($templateHtml); } } return $templateHtml; } function frontRequestHostForSite($site, $currentDomain = '') { $current = normalizeSiteDomain($currentDomain); if ($current !== '' && siteMatchesDomain($site, $current)) { return $current; } return getPrimaryDomain($site['domain'] ?? ''); } function frontUseRequestHostForCanonical($site, $currentDomain = '') { if (!is_array($site)) { return $site; } $host = frontRequestHostForSite($site, $currentDomain); if ($host !== '') { $site['request_domain'] = $host; $site['canonical_domain'] = $host; $site['domain'] = $host; } return $site; } function frontInternalAnchorPathForSubdomainHref($href, $baseDomain) { $href = trim(html_entity_decode((string)$href, ENT_QUOTES | ENT_HTML5, 'UTF-8')); if ($href === '' || preg_match('/^(?:mailto|tel|sms|javascript|data):/i', $href)) { return null; } if ($href[0] === '#') { return '/'; } if (strpos($href, '//') === 0) { $href = 'https:' . $href; } if (preg_match('#^https?://#i', $href)) { $host = normalizeSiteDomain(parse_url($href, PHP_URL_HOST) ?: ''); if ($host === '' || getRegistrableDomain($host) !== $baseDomain) { return null; } $path = parse_url($href, PHP_URL_PATH); if ($path === null || $path === false || $path === '') { $path = '/'; } $query = parse_url($href, PHP_URL_QUERY); if ($query !== null && $query !== false && $query !== '') { $path .= '?' . $query; } return $path; } if ($href[0] === '/') { return $href; } return null; } function frontFixedCurrentHostAnchorPath($open, $tag, $path, $language = 'zh-CN') { $open = (string)$open; $tag = (string)$tag; $path = (string)$path; $pathOnly = $path; $query = ''; $queryPos = strpos($pathOnly, '?'); if ($queryPos !== false) { $query = substr($pathOnly, $queryPos); $pathOnly = substr($pathOnly, 0, $queryPos); } if ($pathOnly === '') { $pathOnly = '/'; } $isBrand = function_exists('templateHtmlClassContains') && templateHtmlClassContains($open, ['brand', 'logo', 'site-title', 'site-name', 'navbar-brand', 'nav-brand', 'brand-name', 'brand-text', 'header-title', 'site-logo', 'nav-logo']); $isHomeText = function_exists('templateNavBodyHasHome') && templateNavBodyHasHome($tag, $language); $isNewsText = function_exists('templateNavBodyHasNews') && templateNavBodyHasNews($tag, $language); if ($isBrand || $isHomeText) { return '/'; } if ($isNewsText && ($pathOnly === '/' || $pathOnly === '#')) { return '/news/'; } if ($pathOnly === '/sitemap.xml') { return '/sitemap.xml'; } if (preg_match('#^/news(?:/|$)#i', $pathOnly)) { return $pathOnly . $query; } return null; } function frontDiversifySubdomainHrefLinks($html, $site, $currentDomain = '') { $html = (string)$html; if ($html === '' || stripos($html, ']*>[\s\S]*?/i', function($matches) use ($baseDomain, $pool, $rewriteSubdomainHrefs, $salt, $requestHost, $language, &$counter, &$usedHosts) { $tag = $matches[0]; if (!preg_match('/^]*>/i', $tag, $openMatch)) { return $tag; } $open = $openMatch[0]; if (stripos($open, 'href') === false) { return $tag; } $href = templateHtmlGetAttribute($open, 'href'); $path = frontInternalAnchorPathForSubdomainHref($href, $baseDomain); if ($path === null) { return $tag; } $fixedPath = frontFixedCurrentHostAnchorPath($open, $tag, $path, $language); if ($fixedPath !== null) { $newOpen = templateHtmlSetAttribute($open, 'href', getCanonicalSiteUrl($requestHost, $fixedPath)); return $newOpen . substr($tag, strlen($open)); } if (!$rewriteSubdomainHrefs) { return $tag; } $counter++; $host = templatePickDistinctFragmentHrefHost($pool, $salt, $href . '|' . $counter . '|' . $open, $usedHosts); if ($host === '') { return $tag; } $newOpen = templateHtmlSetAttribute($open, 'href', getCanonicalSiteUrl($host, '/')); return $newOpen . substr($tag, strlen($open)); }, $html); } function frontOutputFavicon($site) { require_once __DIR__ . '/includes/image_generator.php'; $templateHtml = frontLoadNormalizedBrandTemplateHtml($site); $assets = ensureSiteBrandAssets( $site['id'] ?? '', $site['title'] ?? '', $site['domain'] ?? '', $site['industry'] ?? '', $site['core_keyword'] ?? '', $templateHtml ); $path = $assets['favicon_path'] ?? ''; if ($path === '' || !is_file($path)) { http_response_code(404); header('Content-Type: text/plain; charset=utf-8'); echo "Not found\n"; return; } header('Content-Type: image/x-icon'); header('Cache-Control: public, max-age=300, must-revalidate'); header('Content-Length: ' . filesize($path)); readfile($path); } function frontOutputAppleTouchIcon($site) { require_once __DIR__ . '/includes/image_generator.php'; $templateHtml = frontLoadNormalizedBrandTemplateHtml($site); $assets = ensureSiteBrandAssets( $site['id'] ?? '', $site['title'] ?? '', $site['domain'] ?? '', $site['industry'] ?? '', $site['core_keyword'] ?? '', $templateHtml ); $path = $assets['apple_path'] ?? ($assets['logo_path'] ?? ''); if ($path === '' || !is_file($path)) { http_response_code(404); header('Content-Type: text/plain; charset=utf-8'); echo "Not found\n"; return; } header('Content-Type: image/png'); header('Cache-Control: public, max-age=300, must-revalidate'); header('Content-Length: ' . filesize($path)); readfile($path); } function frontBuildContactBar() { $contact = trim((string)getConfig('site_contact_info', '')); if ($contact === '') { return ''; } $contact = preg_replace('/\s+/u', ' ', $contact); $contact = trim($contact); if ($contact === '') { return ''; } $contactHtml = htmlspecialchars($contact, ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8'); return 联系方式{$contactHtml} HTML; } function frontApplyContactBar($html) { $statusCode = (int)http_response_code(); if ($statusCode >= 400) { return (string)$html; } $contactBar = frontBuildContactBar(); if ($contactBar === '') { return (string)$html; } if (stripos((string)$html, 'site-contact-fixed') !== false) { return (string)$html; } if (stripos((string)$html, '') !== false) { return str_ireplace('', $contactBar . "\n", (string)$html); } return (string)$html . $contactBar; } function frontOutputHtml($html, $previewDomain = '') { $html = (string)$html; $html = frontApplyContactBar($html); // 广告和统计统一由 add.js 负责。这里不再把旧版内联代码注入 // HTML,避免 PC、蜘蛛和移动搜索访问出现重复脚本或重复广告。 $html = addJsLoaderInjectHead($html, $previewDomain); if (frontApplyHtmlCacheValidators($html, $previewDomain)) { if (function_exists('tongjiBridgeFinishResponse')) { tongjiBridgeFinishResponse(); } return; } if (strtoupper((string)($_SERVER['REQUEST_METHOD'] ?? 'GET')) !== 'HEAD') { echo $html; } // Let PHP-FPM send the crawler response before the shutdown logger // performs its file appends. This keeps statistics without making the // crawler wait for log I/O under concurrent spider traffic. if (function_exists('tongjiBridgeFinishResponse')) { tongjiBridgeFinishResponse(); } } function frontApplyHtmlCacheValidators($html, $previewDomain = '') { if ($previewDomain !== '' || headers_sent() || (int)http_response_code() >= 400) { return false; } $method = strtoupper((string)($_SERVER['REQUEST_METHOD'] ?? 'GET')); if ($method !== 'GET' && $method !== 'HEAD') { return false; } $etag = '"' . hash('sha256', (string)$html) . '"'; header('ETag: ' . $etag); if (!empty($GLOBALS['__add_js_loader_response_injected'])) { // 注入结果取决于 Referer、UA 和 Fetch Metadata,禁止 CDN/浏览器 // 将带 add.js 的搜索访问复用给直接访问或手机模拟请求。 header('Cache-Control: private, no-store, no-cache, must-revalidate, max-age=0'); header('Vary: Referer, User-Agent, Sec-Fetch-Site, Sec-Fetch-Mode, Sec-Fetch-Dest, Sec-Fetch-User, Sec-CH-UA-Mobile'); } else { header('Cache-Control: no-cache, must-revalidate'); } $ifNoneMatch = trim((string)($_SERVER['HTTP_IF_NONE_MATCH'] ?? '')); if ($ifNoneMatch === '') { return false; } $tags = array_map('trim', explode(',', $ifNoneMatch)); if (in_array('*', $tags, true) || in_array($etag, $tags, true) || in_array('W/' . $etag, $tags, true)) { http_response_code(304); return true; } return false; } function frontIsHomepagePath($path) { $path = parse_url((string)$path, PHP_URL_PATH); if (!$path) { return true; } $path = '/' . ltrim($path, '/'); $normalized = rtrim($path, '/'); if ($normalized === '') { $normalized = '/'; } return $normalized === '/' || strtolower($normalized) === '/index.php'; } function frontOutputSite404($site, $homePath = '/') { $language = normalizeSiteLanguage($site['language'] ?? 'zh-CN'); $title = getSiteLocalizedText($language, 'not_found_title'); $description = getSiteLocalizedText($language, 'not_found_description'); $homeUrl = getCanonicalSiteUrl($site['domain'] ?? '', $homePath); if ($homeUrl === '') { $homeUrl = '/'; } http_response_code(404); header('Content-Type: text/html; charset=utf-8'); echo renderNewsLayout( $site, $title, $description, '' . htmlspecialchars($title, ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8') . '' . htmlspecialchars($description, ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8') . 'Home', $homeUrl ); exit; } // 获取当前域名 function frontLegalPageTexts($site, $type) { $language = normalizeSiteLanguage($site['language'] ?? 'zh-CN'); $brand = trim((string)($site['core_keyword'] ?? '')); if ($brand === '') { $brand = trim((string)($site['title'] ?? '')); } if ($brand === '') { $brand = trim((string)($site['domain'] ?? '')); } $isPrivacy = ($type === 'privacy'); $maps = [ 'zh-CN' => [ 'privacy_title' => '隐私政策', 'privacy_description' => '本页面说明本站如何处理访问数据、Cookie、联系请求和基础安全记录。', 'terms_title' => '使用条款', 'terms_description' => '本页面说明本站内容使用规则、责任边界和访问者应遵守的基本条款。', 'privacy_sections' => [ ['信息收集', '本站可能记录必要的访问日志、设备信息、来源页面和基础安全数据,用于维护访问稳定性、排查异常请求和改进页面体验。'], ['Cookie 使用', '本站可能使用必要 Cookie 或同类技术来保持页面功能、统计基础访问表现和识别异常流量。你可以通过浏览器设置管理 Cookie。'], ['联系与安全', '如果你通过页面联系方式提交信息,相关内容仅用于回复请求、处理问题或履行必要的站点管理职责。'], ], 'terms_sections' => [ ['内容用途', '本站内容用于信息展示和主题说明,不构成法律、财务、医疗或其他专业建议。访问者应结合自身情况独立判断。'], ['访问规则', '访问者不得滥用页面功能、干扰站点运行、批量抓取造成异常负载,或将页面内容用于违法违规用途。'], ['责任边界', '本站会尽量保持内容准确和可访问,但不保证所有信息在任何时间都完全无误或持续可用。'], ], ], 'pt-BR' => [ 'privacy_title' => 'Política de Privacidade', 'privacy_description' => 'Esta página resume como o site trata dados de navegação, cookies, contatos e registros básicos de segurança.', 'terms_title' => 'Termos de Uso', 'terms_description' => 'Estes termos explicam regras de uso do conteúdo, limites de responsabilidade e condições gerais de acesso.', 'privacy_sections' => [ ['Dados de navegação', 'O site pode registrar logs essenciais, dados técnicos do dispositivo, páginas de origem e eventos de segurança para manter estabilidade, investigar abuso e melhorar a experiência.'], ['Cookies', 'Podemos usar cookies necessários ou tecnologias semelhantes para funcionamento básico, leitura de métricas agregadas e prevenção de tráfego anormal. Você pode gerenciar cookies no navegador.'], ['Contato e proteção', 'Informações enviadas por canais de contato são usadas para responder solicitações, tratar dúvidas e cumprir rotinas necessárias de administração do site.'], ], 'terms_sections' => [ ['Uso do conteúdo', 'O conteúdo tem finalidade informativa e editorial. Ele não substitui aconselhamento legal, financeiro, médico ou profissional específico.'], ['Conduta de acesso', 'Visitantes não devem abusar de recursos, interferir na operação, gerar carga automatizada anormal ou usar o conteúdo para fins ilegais.'], ['Limites', 'Buscamos manter as páginas corretas e acessíveis, mas não garantimos que toda informação esteja sempre completa, atualizada ou disponível sem interrupção.'], ], ], 'en' => [ 'privacy_title' => 'Privacy Policy', 'privacy_description' => 'This page explains how the site handles browsing data, cookies, contact requests and basic security records.', 'terms_title' => 'Terms of Use', 'terms_description' => 'These terms explain content usage rules, responsibility limits and general access conditions.', 'privacy_sections' => [ ['Browsing data', 'The site may keep essential logs, device information, referrer pages and security events to maintain stability, investigate abuse and improve the experience.'], ['Cookies', 'Necessary cookies or similar technologies may be used for basic functionality, aggregate measurement and abnormal traffic prevention.'], ['Contact information', 'Information sent through contact channels is used to respond to requests, handle questions and support necessary site administration.'], ], 'terms_sections' => [ ['Content use', 'Content is informational and editorial. It does not replace legal, financial, medical or other professional advice.'], ['Access rules', 'Visitors must not misuse functionality, disrupt site operation, create abnormal automated load or use content for unlawful purposes.'], ['Limitations', 'We try to keep pages accurate and accessible, but do not guarantee every detail is always complete, current or uninterrupted.'], ], ], ]; $fallback = $maps[$language] ?? $maps['en']; return [ 'title' => $isPrivacy ? $fallback['privacy_title'] : $fallback['terms_title'], 'description' => $isPrivacy ? $fallback['privacy_description'] : $fallback['terms_description'], 'sections' => $isPrivacy ? $fallback['privacy_sections'] : $fallback['terms_sections'], 'brand' => $brand, ]; } function frontOutputLegalPage($site, $type, $previewDomain = '') { $type = $type === 'terms' ? 'terms' : 'privacy'; $data = frontLegalPageTexts($site, $type); $pageHeading = $data['title']; $brand = newsCleanText($site['core_keyword'] ?? '', 48); if ($brand === '') { $brand = newsShortSiteName($site); } $title = $pageHeading; if ($brand !== '' && strpos($title, $brand) === false) { $title .= ' - ' . $brand; } $description = $data['description']; $canonical = getCanonicalSiteUrl($site['domain'] ?? '', '/' . $type . '/'); $body = '' . newsBreadcrumbHtml($site, $pageHeading) . '' . htmlspecialchars($pageHeading, ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8') . '' . htmlspecialchars($description, ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8') . '' . ''; foreach ($data['sections'] as $section) { $body .= '' . htmlspecialchars($section[0], ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8') . '' . htmlspecialchars($section[1], ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8') . ''; } $body .= ''; header('Content-Type: text/html; charset=utf-8'); frontOutputHtml(renderNewsLayout($site, $title, $description, $body, $canonical, '', 'article', 'website'), $previewDomain); exit; } $currentDomain = $_SERVER['HTTP_HOST'] ?? ''; $requestPath = frontRequestPath(); // The root-level news directory is a server-side content library for pan // pages, not a public document tree. Block source-file extensions if the web // server forwards the request to PHP instead of serving the static file first. // Keep /news/ and generated .html/.shtml article URLs available. if (preg_match('#^/news/.+\.(?:txt|md|json)(?:/)?$#i', $requestPath)) { http_response_code(404); header('Content-Type: text/plain; charset=utf-8'); header('X-Robots-Tag: noindex, nofollow, noarchive', true); echo "Not found\n"; exit; } frontRouteAdminAlias($requestPath); // 支持预览模式(后台预览) $previewDomain = $_GET['preview_domain'] ?? ''; if ($previewDomain) { $currentDomain = $previewDomain; } // 根据域名查找站点 $site = getSiteByDomain($currentDomain); if ($site && !$previewDomain) { $site = frontUseRequestHostForCanonical($site, $currentDomain); } if ($site && !$previewDomain) { try { tongjiRecordRequest($site); } catch (Throwable $e) { if (function_exists('appLog')) { appLog('tongji_runtime_error', 'Tongji 统计桥接运行异常,已跳过本次统计', [ 'error' => $e->getMessage(), 'file' => $e->getFile(), 'line' => $e->getLine(), ], 'warning'); } } } $isIndexNowKeyRequest = $site ? searchEngineIsIndexNowKeyRequest($requestPath, $site['domain'] ?? '') : false; if (!$previewDomain && ($requestPath === '/robots.txt' || preg_match('#^/sitemap(?:-static|-pan-[0-9]+)?\.xml$#i', $requestPath) || $requestPath === '/favicon.ico' || $requestPath === '/apple-touch-icon.png' || $isIndexNowKeyRequest)) { if (!$site) { http_response_code(404); header('Content-Type: text/plain; charset=utf-8'); echo "Not found\n"; exit; } if ($requestPath === '/robots.txt') { frontOutputRobots($site); } elseif ($requestPath === '/favicon.ico') { frontOutputFavicon($site); } elseif ($requestPath === '/apple-touch-icon.png') { frontOutputAppleTouchIcon($site); } elseif ($isIndexNowKeyRequest) { searchEngineOutputIndexNowKey($site['domain'] ?? ''); } else { frontOutputSitemap($site, $currentDomain, $requestPath); } exit; } if (!$site) { // 未找到站点,显示404 http_response_code(404); ?> 页面未找到 404 站点未找到 当前域名尚未配置站点页面 /">进入后台管理 ' . htmlspecialchars(getSiteLocalizedText($site['language'] ?? 'zh-CN', 'not_found_title'), ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8') . '' . htmlspecialchars(getSiteLocalizedText($site['language'] ?? 'zh-CN', 'not_found_description'), ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8') . '', getCanonicalSiteUrl($site['domain'] ?? '', '/') ); exit; } $language = normalizeSiteLanguage($site['language'] ?? 'zh-CN'); $title = getSiteLocalizedText($language, 'compliance_page_title'); $description = getSiteLocalizedText($language, 'compliance_page_description'); $canonical = getCanonicalSiteUrl($site['domain'] ?? '', '/responsible-gambling/'); $body = '' . newsBreadcrumbHtml($site, $title) . '' . htmlspecialchars($title, ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8') . '' . htmlspecialchars($description, ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8') . '' . (function_exists('renderGamblingComplianceSection') ? renderGamblingComplianceSection($language) : '') . ''; header('Content-Type: text/html; charset=utf-8'); frontOutputHtml(renderNewsLayout($site, $title, $description, $body, $canonical, '', 'article', 'website'), $previewDomain); exit; } if (!$previewDomain && ($requestPath === '/privacy' || $requestPath === '/terms')) { $target = $requestPath === '/privacy' ? '/privacy/' : '/terms/'; header('Location: ' . getCanonicalSiteUrl($site['domain'] ?? '', $target), true, 301); exit; } if (!$previewDomain && ($requestPath === '/privacy/' || $requestPath === '/terms/')) { frontOutputLegalPage($site, trim($requestPath, '/'), $previewDomain); } if (!$previewDomain && newsIsIndexPath($requestPath)) { $newsPage = newsPageFromPath($requestPath); if ($newsPage $maxNewsPage) { header('Location: ' . newsIndexUrl($site, $maxNewsPage), true, 301); exit; } header('Content-Type: text/html; charset=utf-8'); frontOutputHtml(renderNewsIndexPage($site, $newsPage), $previewDomain); exit; } if (!$previewDomain) { $newsSlug = newsSlugFromPath($requestPath); if ($newsSlug !== '') { $article = getNewsArticleByPublicSlug($site, $newsSlug); if (!$article) { http_response_code(404); header('Content-Type: text/html; charset=utf-8'); echo renderNewsLayout( $site, '资讯文章未找到', '当前资讯文章不存在或已经被删除。', '资讯文章未找到当前资讯文章不存在或已经被删除。返回资讯列表', newsUrl($site, '/news/') ); exit; } $canonicalNewsPath = parse_url(newsArticleUrl($site, $article), PHP_URL_PATH) ?: ''; if ($canonicalNewsPath !== '' && $requestPath !== $canonicalNewsPath) { header('Location: ' . newsArticleUrl($site, $article), true, 301); exit; } header('Content-Type: text/html; charset=utf-8'); frontOutputHtml(renderNewsArticlePage($site, $article), $previewDomain); exit; } } if (!$previewDomain && !frontIsHomepagePath($requestPath)) { frontOutputSite404($site); } // 查找模板文件 $templateFile = getTemplateFilePath($site['id']); if (!file_exists($templateFile)) { // 站点存在但模板未生成 ?> 🚧 站点页面正在建设中,请稍后再访问 $site['id'] ?? '', 'path' => $templateFile, ]); http_response_code(500); echo '模板文件读取失败,请检查文件权限'; exit; } $normalizedHtml = normalizeGeneratedImageTags($html); $normalizedHtml = prioritizeTemplateHeroImage($normalizedHtml); if ($normalizedHtml !== $html) { $html = $normalizedHtml; if (@file_put_contents($templateFile, $html) === false) { appLog('template_write_error', '清理本地图片尺寸属性后写回失败', [ 'site_id' => $site['id'] ?? '', 'path' => $templateFile, ]); } } // 兼容旧模板:如果模板里还残留随机远程图,访问时快速替换成本地图片并入队异步补图。 if (preg_match('/(?:picsum\.photos|source\.unsplash\.com|images\.unsplash\.com|via\.placeholder\.com|placehold\.co|placekitten\.com)/i', $html)) { $imageResult = processTemplateImages( $html, $site['id'], $site['title'] ?? '', $site['description'] ?? '', $site['domain'] ?? '', $site['industry'] ?? '', $site['core_keyword'] ?? '' ); if (!empty($imageResult['html']) && $imageResult['html'] !== $html) { $html = $imageResult['html']; if (@file_put_contents($templateFile, $html) === false) { appLog('template_write_error', '旧模板图片本地化后写回失败', [ 'site_id' => $site['id'] ?? '', 'path' => $templateFile, ]); } else { appLog('image_queue_info', '旧模板图片已自动本地化并加入队列', [ 'site_id' => $site['id'] ?? '', 'localized' => $imageResult['localized'] ?? 0, 'queued' => $imageResult['queued'] ?? 0, ], 'info'); } } } $brandedHtml = ensureTemplateBrandAssets( $html, $site['id'] ?? '', $site['title'] ?? '', $site['domain'] ?? '', $site['industry'] ?? '', $site['core_keyword'] ?? '', $site['language'] ?? 'zh-CN' ); $brandedHtml = ensureTemplateHomeNavigation( $brandedHtml, $site['domain'] ?? '', $site['language'] ?? 'zh-CN' ); if (function_exists('cleanupTemplateBrandAnchorClosings')) { $brandedHtml = cleanupTemplateBrandAnchorClosings($brandedHtml); } $frontSeoTitle = $site['title'] ?? ''; $frontSeoDescription = $site['description'] ?? ''; $frontSeoKeywords = $site['keywords'] ?? ''; if (function_exists('seoDowngradeSensitiveMetadata')) { $frontSafeMeta = seoDowngradeSensitiveMetadata([ 'title' => $frontSeoTitle, 'description' => $frontSeoDescription, 'keywords' => $frontSeoKeywords, 'core_keyword' => $site['core_keyword'] ?? '', 'industry' => $site['industry'] ?? '', ], $site['language'] ?? 'zh-CN'); $frontSeoTitle = $frontSafeMeta['title'] ?? $frontSeoTitle; $frontSeoDescription = $frontSafeMeta['description'] ?? $frontSeoDescription; $frontSeoKeywords = $frontSafeMeta['keywords'] ?? $frontSeoKeywords; } $frontDisplayTitle = trim((string)($site['core_keyword'] ?? '')); if ($frontDisplayTitle === '') { $frontDisplayTitle = trim((string)$frontSeoTitle); } if (function_exists('seoDowngradeSensitiveHtmlHeadings')) { $brandedHtml = seoDowngradeSensitiveHtmlHeadings($brandedHtml, $site['language'] ?? 'zh-CN', $frontSeoTitle, $frontSeoDescription, $frontSeoKeywords, $site['core_keyword'] ?? '', $site['industry'] ?? ''); } $frontNewsArticlesForDate = loadNewsArticles($site['id'] ?? ''); $frontModifiedTimestamp = max( frontTemplateLastmodTimestamp($site, $templateFile), frontNewsLastmodTimestamp($site, $frontNewsArticlesForDate) ); $frontModifiedDate = frontTimestampDate($frontModifiedTimestamp, date('Y-m-d')); $frontLogoUrl = function_exists('templateSiteLogoUrlForSeo') ? templateSiteLogoUrlForSeo($site['id'] ?? '', $frontDisplayTitle, $site['domain'] ?? '', $site['industry'] ?? '', $site['core_keyword'] ?? '', $brandedHtml) : ''; if (function_exists('injectSeoIntoHtml')) { $brandedHtml = injectSeoIntoHtml( $brandedHtml, $frontSeoTitle, $frontSeoDescription, $site['domain'] ?? '', $frontSeoKeywords, $site['language'] ?? 'zh-CN', $frontDisplayTitle, $frontModifiedDate, $frontLogoUrl ); } if (function_exists('enforceTemplateExactTitle')) { $brandedHtml = enforceTemplateExactTitle($brandedHtml, $frontSeoTitle); } if (function_exists('enforceTemplateExactH1')) { $brandedHtml = enforceTemplateExactH1($brandedHtml, $frontDisplayTitle); } if (function_exists('ensureTemplateGamblingCompliance')) { $brandedHtml = ensureTemplateGamblingCompliance( $brandedHtml, $frontDisplayTitle, $frontSeoDescription, $site['industry'] ?? '', $site['core_keyword'] ?? '', $frontSeoKeywords, $site['language'] ?? 'zh-CN' ); } if (function_exists('removeTemplateHeadingEmojisForSensitiveSites')) { $brandedHtml = removeTemplateHeadingEmojisForSensitiveSites($brandedHtml, $frontDisplayTitle, $frontSeoDescription, $site['industry'] ?? '', $site['core_keyword'] ?? '', $frontSeoKeywords); } if (function_exists('normalizeTemplateFooterYear')) { $brandedHtml = normalizeTemplateFooterYear($brandedHtml); } if ($brandedHtml !== $html) { $html = $brandedHtml; if (@file_put_contents($templateFile, $html) === false) { appLog('template_write_error', '写入站点品牌资源失败', [ 'site_id' => $site['id'] ?? '', 'path' => $templateFile, ]); } } $html = injectNewsSectionIntoHomepage($html, $site, 4); $html = frontDiversifySubdomainHrefLinks($html, $site, $currentDomain); frontOutputHtml($html, $previewDomain); if (!$previewDomain) { triggerAutoNewsAfterResponse($site, 'front_visit'); } exit;
网站标题
千寻网-千寻收录网,千寻网导航,免费友情链接,网址导航,收录网站,免费提交,自动审核
关键词
千寻网,千寻收录网,千寻网导航,导航收录网,万能秒收录,网站分类目录,网站目录,分类目录,名站导航,网址提交,网站大全
站点描述
千寻网导航是一个集合众多网站的网址导航站点,包含了各类网站的分类导航,如资源博客、网址导航、影视视频、电影短剧、网路资讯等,涵盖了网民日常使用的各类网站