diff --git a/api/version/media-url.php b/api/version/media-url.php index 0d25c70..5f5516f 100644 --- a/api/version/media-url.php +++ b/api/version/media-url.php @@ -357,7 +357,8 @@ if ($download) { $filename = null; $cd = $parsed['content-disposition'] ?? null; if ($cd) { - if (preg_match('/filename\*=(?:[^']*'')?(.+)$/i', $cd, $m)) { + // Usar comillas dobles para el regex que contiene apóstrofes + if (preg_match("/filename\\*=(?:[^']*'')?(.+)$/i", $cd, $m)) { $filename = trim($m[1], " \"'\r\n"); $filename = rawurldecode($filename); } elseif (preg_match('/filename="?([^";]+)"?/i', $cd, $m)) { @@ -454,7 +455,65 @@ if (!$wantsJson && !empty($resolvedFromGraph) && $resolvedFromGraph) { exit; } -// Por defecto redirigir al URL (navegador hará la descarga o mostrará la imagen) +// Por defecto: si la URL parece pertenecer a Facebook/lookaside y disponemos de token, proxificar con Authorization +$parsed = parse_url($mediaUrl); +$host = isset($parsed['host']) ? strtolower($parsed['host']) : ''; +$token = getConfigFromDB('whatsapp_token', ''); +$shouldProxy = false; +if ($token && ($host === 'lookaside.fbsbx.com' || stripos($host, 'graph.facebook.com') !== false || stripos($host, 'facebook.com') !== false)) { + $shouldProxy = true; +} + +if ($shouldProxy) { + media_log("Proxying Facebook media URL with Authorization to {$mediaUrl}"); + $ch = curl_init(); + $headers = ['User-Agent: WhatsAppMediaProxy/1.0', 'Accept: */*']; + if ($token) $headers[] = 'Authorization: Bearer ' . $token; + + curl_setopt_array($ch, [ + CURLOPT_URL => $mediaUrl, + CURLOPT_RETURNTRANSFER => true, + CURLOPT_FOLLOWLOCATION => true, + CURLOPT_TIMEOUT => 60, + CURLOPT_HTTPHEADER => $headers, + CURLOPT_HEADER => true, + ]); + $response = curl_exec($ch); + $info = curl_getinfo($ch); + $err = curl_error($ch); + curl_close($ch); + + if ($err) { + http_response_code(502); + header('Content-Type: application/json; charset=utf-8'); + echo json_encode(['success' => false, 'error' => 'Error al descargar el archivo (proxy)', 'detail' => $err]); + exit; + } + + $remoteHttp = isset($info['http_code']) ? (int)$info['http_code'] : 0; + if ($remoteHttp >= 400) { + http_response_code(502); + header('Content-Type: application/json; charset=utf-8'); + echo json_encode(['success' => false, 'error' => 'Remote server returned error status', 'http_code' => $remoteHttp, 'url' => $mediaUrl]); + exit; + } + + $headerSize = isset($info['header_size']) ? (int)$info['header_size'] : 0; + $headersText = $headerSize ? substr($response, 0, $headerSize) : ''; + $body = $headerSize ? substr($response, $headerSize) : $response; + + // Parsear content-type desde headers devueltos + $contentType = $info['content_type'] ?? null; + + header_remove('Content-Type'); + header('Cache-Control: public, max-age=3600'); + if (!empty($contentType)) header('Content-Type: ' . $contentType); + header('Content-Length: ' . strlen($body)); + echo $body; + exit; +} + +// Fallback: redirigir al URL (navegador hará la descarga o mostrará la imagen) header('Cache-Control: public, max-age=3600'); header('Location: ' . $mediaUrl, true, 302); exit; diff --git a/api/version/media-url_debug.log b/api/version/media-url_debug.log new file mode 100644 index 0000000..6dda3ea --- /dev/null +++ b/api/version/media-url_debug.log @@ -0,0 +1,11 @@ +[2026-01-21 14:06:30] Request: GET /api/version/media-url.php?id=2690520987949889 GET:{"id":"2690520987949889"} POST:[] +[2026-01-21 14:06:30] Graph API request to https://graph.facebook.com/v22.0/2690520987949889 +[2026-01-21 14:06:43] Request: GET /api/version/media-url.php?id=2690520987949889 GET:{"id":"2690520987949889"} POST:[] +[2026-01-21 14:06:43] Graph API request to https://graph.facebook.com/v22.0/2690520987949889 +[2026-01-21 14:07:25] Request: GET /api/version/media-url.php?id=2690520987949889 GET:{"id":"2690520987949889"} POST:[] +[2026-01-21 14:07:25] Graph API request to https://graph.facebook.com/v22.0/2690520987949889 +[2026-01-21 14:07:40] Request: GET /api/version/media-url.php?id=2690520987949889 GET:{"id":"2690520987949889"} POST:[] +[2026-01-21 14:07:40] Graph API request to https://graph.facebook.com/v22.0/2690520987949889 +[2026-01-21 14:09:48] Request: GET /api/version/media-url.php?id=2690520987949889 GET:{"id":"2690520987949889"} POST:[] +[2026-01-21 14:09:48] Graph API request to https://graph.facebook.com/v22.0/2690520987949889 +[2026-01-21 14:09:49] Proxying Facebook media URL with Authorization to https://lookaside.fbsbx.com/whatsapp_business/attachments/?mid=2690520987949889&source=getMedia&ext=1769022879&hash=ARmZNGo6nPUMqsu1WVi5OGDOIQucpHkU45UcMnR0kudP2Q