mirror of
https://github.com/manualdousuario/marreta.git
synced 2025-09-04 11:41:12 +00:00
implementado fastroute para controle e segurança de rotas
This commit is contained in:
parent
4cd475c8ef
commit
bc06a7cbc9
12 changed files with 570 additions and 539 deletions
133
app/api.php
133
app/api.php
|
@ -1,133 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
/**
|
|
||||||
* URL Analysis API
|
|
||||||
* API para análise de URLs
|
|
||||||
*
|
|
||||||
* This file implements a REST endpoint that receives URLs via GET
|
|
||||||
* and returns processed results in JSON format.
|
|
||||||
*
|
|
||||||
* Este arquivo implementa um endpoint REST que recebe URLs via GET
|
|
||||||
* e retorna resultados processados em formato JSON.
|
|
||||||
*
|
|
||||||
* Features / Funcionalidades:
|
|
||||||
* - URL validation / Validação de URLs
|
|
||||||
* - Content analysis / Análise de conteúdo
|
|
||||||
* - Error handling / Tratamento de erros
|
|
||||||
* - CORS support / Suporte a CORS
|
|
||||||
*/
|
|
||||||
|
|
||||||
require_once 'config.php';
|
|
||||||
require_once 'inc/URLAnalyzer.php';
|
|
||||||
require_once 'inc/Language.php';
|
|
||||||
|
|
||||||
// Initialize language system with default language
|
|
||||||
// Inicializa o sistema de idiomas com o idioma padrão
|
|
||||||
Language::init(LANGUAGE);
|
|
||||||
|
|
||||||
// Set content type as JSON
|
|
||||||
// Define o tipo de conteúdo como JSON
|
|
||||||
header('Content-Type: application/json');
|
|
||||||
|
|
||||||
// Enable CORS (Cross-Origin Resource Sharing)
|
|
||||||
// Habilita CORS (Cross-Origin Resource Sharing)
|
|
||||||
header('Access-Control-Allow-Origin: *');
|
|
||||||
header('Access-Control-Allow-Methods: GET');
|
|
||||||
|
|
||||||
// Get request URL from path
|
|
||||||
// Obtém a URL da requisição a partir do path
|
|
||||||
$path = $_SERVER['REQUEST_URI'];
|
|
||||||
$prefix = '/api/';
|
|
||||||
|
|
||||||
if (strpos($path, $prefix) === 0) {
|
|
||||||
$url = urldecode(substr($path, strlen($prefix)));
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Function to send standardized JSON response
|
|
||||||
* Função para enviar resposta JSON padronizada
|
|
||||||
*
|
|
||||||
* @param array $data Data to be sent in response / Dados a serem enviados na resposta
|
|
||||||
* @param int $statusCode HTTP status code / Código de status HTTP
|
|
||||||
*/
|
|
||||||
function sendResponse($data, $statusCode = 200)
|
|
||||||
{
|
|
||||||
http_response_code($statusCode);
|
|
||||||
$response = [
|
|
||||||
'status' => $statusCode
|
|
||||||
];
|
|
||||||
|
|
||||||
if (isset($data['error'])) {
|
|
||||||
$response['error'] = $data['error'];
|
|
||||||
} else if (isset($data['url'])) {
|
|
||||||
$response['url'] = $data['url'];
|
|
||||||
}
|
|
||||||
|
|
||||||
echo json_encode($response);
|
|
||||||
exit;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Basic URL validation
|
|
||||||
// Validação básica da URL
|
|
||||||
if (!$url || !filter_var($url, FILTER_VALIDATE_URL)) {
|
|
||||||
sendResponse([
|
|
||||||
'error' => [
|
|
||||||
'type' => URLAnalyzer::ERROR_INVALID_URL,
|
|
||||||
'message' => Language::getMessage('INVALID_URL')['message']
|
|
||||||
]
|
|
||||||
], 400);
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
// Instantiate URL analyzer
|
|
||||||
// Instancia o analisador de URLs
|
|
||||||
$analyzer = new URLAnalyzer();
|
|
||||||
|
|
||||||
// Try to analyze the provided URL
|
|
||||||
// Tenta analisar a URL fornecida
|
|
||||||
$analyzer->analyze($url);
|
|
||||||
|
|
||||||
// If analysis is successful, return the processed URL
|
|
||||||
// Se a análise for bem-sucedida, retorna a URL processada
|
|
||||||
sendResponse([
|
|
||||||
'url' => SITE_URL . '/p/' . $url
|
|
||||||
], 200);
|
|
||||||
} catch (URLAnalyzerException $e) {
|
|
||||||
// Get error details from the exception
|
|
||||||
// Obtém detalhes do erro da exceção
|
|
||||||
$errorType = $e->getErrorType();
|
|
||||||
$additionalInfo = $e->getAdditionalInfo();
|
|
||||||
|
|
||||||
// Add error header for better client-side handling
|
|
||||||
// Adiciona header de erro para melhor tratamento no cliente
|
|
||||||
header('X-Error-Type: ' . $errorType);
|
|
||||||
if ($additionalInfo) {
|
|
||||||
header('X-Error-Info: ' . $additionalInfo);
|
|
||||||
}
|
|
||||||
|
|
||||||
sendResponse([
|
|
||||||
'error' => [
|
|
||||||
'type' => $errorType,
|
|
||||||
'message' => $e->getMessage(),
|
|
||||||
'details' => $additionalInfo ?: null
|
|
||||||
]
|
|
||||||
], $e->getCode());
|
|
||||||
} catch (Exception $e) {
|
|
||||||
// Handle any other unexpected errors
|
|
||||||
// Trata quaisquer outros erros inesperados
|
|
||||||
sendResponse([
|
|
||||||
'error' => [
|
|
||||||
'type' => URLAnalyzer::ERROR_GENERIC_ERROR,
|
|
||||||
'message' => Language::getMessage('GENERIC_ERROR')['message']
|
|
||||||
]
|
|
||||||
], 500);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// Return 404 error for endpoints not found
|
|
||||||
// Retorna erro 404 para endpoints não encontrados
|
|
||||||
sendResponse([
|
|
||||||
'error' => [
|
|
||||||
'type' => URLAnalyzer::ERROR_NOT_FOUND,
|
|
||||||
'message' => Language::getMessage('NOT_FOUND')['message']
|
|
||||||
]
|
|
||||||
], 404);
|
|
||||||
}
|
|
|
@ -4,11 +4,13 @@
|
||||||
"aws/aws-sdk-php": "^3.0",
|
"aws/aws-sdk-php": "^3.0",
|
||||||
"php-curl-class/php-curl-class": "^11.0",
|
"php-curl-class/php-curl-class": "^11.0",
|
||||||
"php-webdriver/webdriver": "^1.15",
|
"php-webdriver/webdriver": "^1.15",
|
||||||
"monolog/monolog": "^3.8.1"
|
"monolog/monolog": "^3.8.1",
|
||||||
|
"nikic/fast-route": "^1.3"
|
||||||
},
|
},
|
||||||
"autoload": {
|
"autoload": {
|
||||||
"psr-4": {
|
"psr-4": {
|
||||||
"Inc\\": "inc/"
|
"Inc\\": "inc/",
|
||||||
|
"App\\": "src/"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,10 +16,10 @@
|
||||||
* - Selenium extraction support when enabled by domain / Suporte a extração via Selenium quando habilitado por domínio
|
* - Selenium extraction support when enabled by domain / Suporte a extração via Selenium quando habilitado por domínio
|
||||||
*/
|
*/
|
||||||
|
|
||||||
require_once 'Rules.php';
|
require_once __DIR__ . '/Rules.php';
|
||||||
require_once 'Cache.php';
|
require_once __DIR__ . '/Cache.php';
|
||||||
require_once 'Logger.php';
|
require_once __DIR__ . '/Logger.php';
|
||||||
require_once 'Language.php';
|
require_once __DIR__ . '/Language.php';
|
||||||
|
|
||||||
use Curl\Curl;
|
use Curl\Curl;
|
||||||
use Facebook\WebDriver\Remote\DesiredCapabilities;
|
use Facebook\WebDriver\Remote\DesiredCapabilities;
|
||||||
|
@ -253,14 +253,14 @@ class URLAnalyzer
|
||||||
$host = preg_replace('/^www\./', '', $host);
|
$host = preg_replace('/^www\./', '', $host);
|
||||||
|
|
||||||
if (in_array($host, BLOCKED_DOMAINS)) {
|
if (in_array($host, BLOCKED_DOMAINS)) {
|
||||||
Logger::getInstance()->log($cleanUrl, 'BLOCKED_DOMAIN');
|
Logger::getInstance()->logUrl($cleanUrl, 'BLOCKED_DOMAIN');
|
||||||
$this->throwError(self::ERROR_BLOCKED_DOMAIN);
|
$this->throwError(self::ERROR_BLOCKED_DOMAIN);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check URL status code before proceeding
|
// Check URL status code before proceeding
|
||||||
$redirectInfo = $this->checkStatus($cleanUrl);
|
$redirectInfo = $this->checkStatus($cleanUrl);
|
||||||
if ($redirectInfo['httpCode'] !== 200) {
|
if ($redirectInfo['httpCode'] !== 200) {
|
||||||
Logger::getInstance()->log($cleanUrl, 'INVALID_STATUS_CODE', "HTTP {$redirectInfo['httpCode']}");
|
Logger::getInstance()->logUrl($cleanUrl, 'INVALID_STATUS_CODE', "HTTP {$redirectInfo['httpCode']}");
|
||||||
if ($redirectInfo['httpCode'] === 404) {
|
if ($redirectInfo['httpCode'] === 404) {
|
||||||
$this->throwError(self::ERROR_NOT_FOUND);
|
$this->throwError(self::ERROR_NOT_FOUND);
|
||||||
} else {
|
} else {
|
||||||
|
@ -296,7 +296,7 @@ class URLAnalyzer
|
||||||
return $processedContent;
|
return $processedContent;
|
||||||
}
|
}
|
||||||
} catch (Exception $e) {
|
} catch (Exception $e) {
|
||||||
Logger::getInstance()->log($cleanUrl, strtoupper($fetchStrategy) . '_ERROR', $e->getMessage());
|
Logger::getInstance()->logUrl($cleanUrl, strtoupper($fetchStrategy) . '_ERROR', $e->getMessage());
|
||||||
throw $e;
|
throw $e;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -326,7 +326,7 @@ class URLAnalyzer
|
||||||
}
|
}
|
||||||
|
|
||||||
// If we get here, all strategies failed
|
// If we get here, all strategies failed
|
||||||
Logger::getInstance()->log($cleanUrl, 'GENERAL_FETCH_ERROR');
|
Logger::getInstance()->logUrl($cleanUrl, 'GENERAL_FETCH_ERROR');
|
||||||
if ($lastError) {
|
if ($lastError) {
|
||||||
$message = $lastError->getMessage();
|
$message = $lastError->getMessage();
|
||||||
if (strpos($message, 'DNS') !== false) {
|
if (strpos($message, 'DNS') !== false) {
|
||||||
|
|
217
app/index.php
217
app/index.php
|
@ -1,214 +1,17 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Página principal do sistema / Main system page
|
* Arquivo de entrada da aplicação
|
||||||
|
* Application entry point
|
||||||
*
|
*
|
||||||
* Este arquivo implementa a interface web principal, incluindo:
|
* Este arquivo inicializa o sistema de roteamento e despacha as requisições
|
||||||
* - Formulário para análise de URLs
|
* para os manipuladores apropriados usando FastRoute.
|
||||||
* - Tratamento de mensagens de erro/sucesso
|
*
|
||||||
* - Documentação da API
|
* This file initializes the routing system and dispatches requests
|
||||||
* - Interface para bookmarklet
|
* to appropriate handlers using FastRoute.
|
||||||
* - Links para serviços alternativos
|
|
||||||
*
|
|
||||||
* This file implements the main web interface, including:
|
|
||||||
* - URL analysis form
|
|
||||||
* - Error/success message handling
|
|
||||||
* - API documentation
|
|
||||||
* - Bookmarklet interface
|
|
||||||
* - Links to alternative services
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
require_once 'config.php';
|
require_once __DIR__ . '/vendor/autoload.php';
|
||||||
require_once 'inc/Cache.php';
|
|
||||||
require_once 'inc/Language.php';
|
|
||||||
|
|
||||||
// Inicialização das traduções / Initialize translations
|
$router = new App\Router();
|
||||||
Language::init(LANGUAGE);
|
$router->dispatch();
|
||||||
|
|
||||||
// Inicialização de variáveis / Variable initialization
|
|
||||||
$message = '';
|
|
||||||
$message_type = '';
|
|
||||||
$url = '';
|
|
||||||
|
|
||||||
// Processa mensagens de erro/alerta da query string / Process error/warning messages from query string
|
|
||||||
if (isset($_GET['message'])) {
|
|
||||||
$message_key = $_GET['message'];
|
|
||||||
$messageData = Language::getMessage($message_key);
|
|
||||||
$message = $messageData['message'];
|
|
||||||
$message_type = $messageData['type'];
|
|
||||||
}
|
|
||||||
|
|
||||||
// Processa submissão do formulário / Process form submission
|
|
||||||
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['url'])) {
|
|
||||||
$url = filter_var($_POST['url'], FILTER_SANITIZE_URL);
|
|
||||||
if (filter_var($url, FILTER_VALIDATE_URL)) {
|
|
||||||
header('Location: ' . SITE_URL . '/p/' . urlencode($url));
|
|
||||||
exit;
|
|
||||||
} else {
|
|
||||||
$messageData = Language::getMessage('INVALID_URL');
|
|
||||||
$message = $messageData['message'];
|
|
||||||
$message_type = $messageData['type'];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Inicializa o cache para contagem / Initialize cache for counting
|
|
||||||
$cache = new Cache();
|
|
||||||
$cache_folder = $cache->getCacheFileCount();
|
|
||||||
?>
|
|
||||||
<!DOCTYPE html>
|
|
||||||
<html lang="<?php echo Language::getCurrentLanguage(); ?>">
|
|
||||||
|
|
||||||
<head>
|
|
||||||
<meta charset="UTF-8">
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover">
|
|
||||||
<title><?php echo SITE_NAME; ?></title>
|
|
||||||
<link rel="icon" href="<?php echo SITE_URL; ?>/assets/svg/marreta.svg" type="image/svg+xml">
|
|
||||||
<meta name="theme-color" content="#2563eb">
|
|
||||||
<link rel="manifest" href="<?php echo SITE_URL; ?>/manifest.json">
|
|
||||||
|
|
||||||
<!-- PWA meta tags -->
|
|
||||||
<meta name="mobile-web-app-capable" content="yes">
|
|
||||||
<meta name="application-name" content="<?php echo SITE_NAME; ?>">
|
|
||||||
|
|
||||||
<!-- Open Graph meta tags -->
|
|
||||||
<meta property="og:type" content="website" />
|
|
||||||
<meta property="og:url" content="<?php echo SITE_URL; ?>" />
|
|
||||||
<meta property="og:title" content="<?php echo SITE_NAME; ?>" />
|
|
||||||
<meta property="og:description" content="<?php echo htmlspecialchars(SITE_DESCRIPTION); ?>" />
|
|
||||||
<meta property="og:image" content="<?php echo SITE_URL; ?>/assets/opengraph.png" />
|
|
||||||
<script src="https://cdn.tailwindcss.com/3.4.15"></script>
|
|
||||||
</head>
|
|
||||||
|
|
||||||
<body class="bg-gray-50 min-h-screen">
|
|
||||||
<div class="container mx-auto px-4 py-8 max-w-4xl">
|
|
||||||
<!-- Cabeçalho da página / Page header -->
|
|
||||||
<div class="text-center mb-8">
|
|
||||||
<h1 class="text-4xl font-bold text-gray-800 mb-4">
|
|
||||||
<img src="assets/svg/marreta.svg" class="inline-block w-12 h-12 mb-2" alt="Marreta">
|
|
||||||
<?php echo SITE_NAME; ?>
|
|
||||||
</h1>
|
|
||||||
<p class="text-gray-600 text-lg"><?php echo SITE_DESCRIPTION; ?></p>
|
|
||||||
<p class="text-gray-600 text-lg">
|
|
||||||
<span class="font-bold text-blue-600">
|
|
||||||
<?php echo number_format($cache_folder, 0, ',', '.'); ?>
|
|
||||||
</span>
|
|
||||||
<span><?php echo Language::get('walls_destroyed'); ?></span>
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Formulário principal de análise de URLs / Main URL analysis form -->
|
|
||||||
<div class="bg-white rounded-xl shadow-lg p-8 mb-8">
|
|
||||||
<form id="urlForm" method="POST" onsubmit="return validateForm()" class="space-y-6">
|
|
||||||
<div class="relative">
|
|
||||||
<div class="flex items-stretch">
|
|
||||||
<span class="inline-flex items-center px-5 rounded-l-lg border border-r-0 border-gray-300 bg-gray-50 text-gray-500">
|
|
||||||
<img src="assets/svg/link.svg" class="w-6 h-6" alt="Link">
|
|
||||||
</span>
|
|
||||||
<input type="url"
|
|
||||||
name="url"
|
|
||||||
id="url"
|
|
||||||
class="flex-1 block w-full rounded-none rounded-r-lg text-lg py-4 border border-l-0 border-gray-300 bg-gray-50 focus:border-blue-500 focus:ring-blue-500 shadow-sm bg-gray-50"
|
|
||||||
placeholder="<?php echo Language::get('url_placeholder'); ?>"
|
|
||||||
value="<?php echo htmlspecialchars($url); ?>"
|
|
||||||
required
|
|
||||||
pattern="https?://.+"
|
|
||||||
title="<?php echo Language::getMessage('INVALID_URL')['message']; ?>">
|
|
||||||
</div>
|
|
||||||
<button type="submit"
|
|
||||||
class="mt-4 w-full inline-flex justify-center items-center px-6 py-4 border border-transparent text-lg font-medium rounded-lg text-white bg-blue-600 hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500 transition-colors duration-200">
|
|
||||||
<img src="assets/svg/search.svg" class="w-6 h-6 mr-3" alt="Search">
|
|
||||||
<?php echo Language::get('analyze_button'); ?>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
|
|
||||||
<!-- Aviso sobre bloqueadores de anúncios / Ad blocker warning -->
|
|
||||||
<div class="mt-4 text-sm text-gray-600 flex items-start">
|
|
||||||
<p><?php echo str_replace('{site_name}', SITE_NAME, Language::get('adblocker_warning')); ?></p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Área de mensagens de erro/alerta / Error/warning message area -->
|
|
||||||
<?php if ($message): ?>
|
|
||||||
<div class="mt-6 <?php echo $message_type === 'error' ? 'bg-red-50 border-red-400' : 'bg-yellow-50 border-yellow-400'; ?> border-l-4 p-4 rounded-r">
|
|
||||||
<div class="flex">
|
|
||||||
<div class="flex-shrink-0">
|
|
||||||
<?php if ($message_type === 'error'): ?>
|
|
||||||
<img src="assets/svg/error.svg" class="w-6 h-6" alt="Error">
|
|
||||||
<?php else: ?>
|
|
||||||
<img src="assets/svg/warning.svg" class="w-6 h-6" alt="Warning">
|
|
||||||
<?php endif; ?>
|
|
||||||
</div>
|
|
||||||
<div class="ml-3">
|
|
||||||
<p class="text-base <?php echo $message_type === 'error' ? 'text-red-700' : 'text-yellow-700'; ?>">
|
|
||||||
<?php echo htmlspecialchars($message); ?>
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<?php endif; ?>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Adicionar como aplicativo / Add as app (mobile only) -->
|
|
||||||
<div class="bg-white rounded-xl shadow-lg p-8 mt-8 mb-8 md:hidden">
|
|
||||||
<h2 class="text-xl font-semibold text-gray-800 mb-6 flex items-center">
|
|
||||||
<img src="assets/svg/marreta.svg" class="w-6 h-6 mr-3" alt="App">
|
|
||||||
<?php echo Language::get('add_as_app'); ?>
|
|
||||||
</h2>
|
|
||||||
<div class="space-y-4">
|
|
||||||
<p class="text-gray-600">
|
|
||||||
<?php echo str_replace('{site_name}', SITE_NAME, Language::get('add_as_app_description')); ?>
|
|
||||||
</p>
|
|
||||||
<div class="bg-gray-50 rounded-lg p-4">
|
|
||||||
<ol class="list-decimal list-inside space-y-2 text-gray-700">
|
|
||||||
<li><?php echo Language::get('add_as_app_step1'); ?></li>
|
|
||||||
<li><?php echo Language::get('add_as_app_step2'); ?></li>
|
|
||||||
<li><?php echo Language::get('add_as_app_step3'); ?></li>
|
|
||||||
<li><?php echo str_replace('{site_name}', SITE_NAME, Language::get('add_as_app_step4')); ?></li>
|
|
||||||
</ol>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Seção de Bookmarklet / Bookmarklet section (desktop only) -->
|
|
||||||
<div class="bg-white rounded-xl shadow-lg p-8 mt-8 mb-8 hidden md:block">
|
|
||||||
<h2 class="text-xl font-semibold text-gray-800 mb-6 flex items-center">
|
|
||||||
<img src="assets/svg/bookmark.svg" class="w-6 h-6 mr-3" alt="Favoritos">
|
|
||||||
<?php echo Language::get('bookmarklet_title'); ?>
|
|
||||||
</h2>
|
|
||||||
<div class="space-y-4">
|
|
||||||
<p class="text-gray-600">
|
|
||||||
<?php echo str_replace('{site_name}', SITE_NAME, Language::get('bookmarklet_description')); ?>
|
|
||||||
</p>
|
|
||||||
<div class="flex justify-center">
|
|
||||||
<a href="javascript:(function(){let currentUrl=window.location.href;window.location.href='<?php echo SITE_URL; ?>/p/'+encodeURIComponent(currentUrl);})()"
|
|
||||||
class="inline-flex items-center px-6 py-3 border-2 border-blue-500 font-medium rounded-lg text-blue-600 bg-white hover:bg-blue-50 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500 transition-colors duration-200 cursor-move"
|
|
||||||
onclick="return false;">
|
|
||||||
<img src="assets/svg/marreta.svg" class="w-5 h-5 mr-2" alt="Marreta">
|
|
||||||
<?php echo str_replace('{site_name}', SITE_NAME, Language::get('open_in')); ?>
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="text-gray-600 text-center text-sm">
|
|
||||||
<p>
|
|
||||||
<?php echo Language::get('open_source_description'); ?>
|
|
||||||
</p>
|
|
||||||
<p class="mt-2">
|
|
||||||
<a href="https://github.com/manualdousuario/marreta/wiki/API-Rest" target="_blank" class="underline">API Rest</a> ● <a href="https://github.com/manualdousuario/marreta/" target="_blank" class="underline">Github</a>
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Scripts JavaScript -->
|
|
||||||
<script>
|
|
||||||
<?php
|
|
||||||
$js_file = 'assets/js/scripts.js';
|
|
||||||
if (file_exists($js_file)) {
|
|
||||||
echo file_get_contents($js_file);
|
|
||||||
}
|
|
||||||
?>
|
|
||||||
</script>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
|
|
95
app/p.php
95
app/p.php
|
@ -1,95 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
/**
|
|
||||||
* URL Processor
|
|
||||||
* Processador de URLs
|
|
||||||
*
|
|
||||||
* This file is responsible for:
|
|
||||||
* - Receiving URLs through the /p/ path
|
|
||||||
* - Validating URL format
|
|
||||||
* - Processing content using URLAnalyzer
|
|
||||||
* - Displaying processed content or redirecting in case of error
|
|
||||||
*
|
|
||||||
* Este arquivo é responsável por:
|
|
||||||
* - Receber URLs através do path /p/
|
|
||||||
* - Validar o formato da URL
|
|
||||||
* - Processar o conteúdo usando o URLAnalyzer
|
|
||||||
* - Exibir o conteúdo processado ou redirecionar em caso de erro
|
|
||||||
*
|
|
||||||
* Usage example / Exemplo de uso:
|
|
||||||
* /p/https://exemplo.com
|
|
||||||
*/
|
|
||||||
|
|
||||||
require_once 'config.php';
|
|
||||||
require_once 'inc/URLAnalyzer.php';
|
|
||||||
|
|
||||||
// Extract URL from request path
|
|
||||||
// Extrai a URL do path da requisição
|
|
||||||
$path = $_SERVER['REQUEST_URI'];
|
|
||||||
$prefix = '/p/';
|
|
||||||
|
|
||||||
if (strpos($path, $prefix) === 0) {
|
|
||||||
// Remove prefix and decode URL
|
|
||||||
// Remove o prefixo e decodifica a URL
|
|
||||||
$url = urldecode(substr($path, strlen($prefix)));
|
|
||||||
|
|
||||||
// Validate URL format
|
|
||||||
// Valida o formato da URL
|
|
||||||
if (filter_var($url, FILTER_VALIDATE_URL)) {
|
|
||||||
$analyzer = new URLAnalyzer();
|
|
||||||
try {
|
|
||||||
// Check for redirects
|
|
||||||
// Verifica se há redirecionamentos
|
|
||||||
$redirectInfo = $analyzer->checkStatus($url);
|
|
||||||
|
|
||||||
// If there's a redirect and the final URL is different
|
|
||||||
// Se houver redirecionamento e a URL final for diferente
|
|
||||||
if ($redirectInfo['hasRedirect'] && $redirectInfo['finalUrl'] !== $url) {
|
|
||||||
// Redirect to final URL
|
|
||||||
// Redireciona para a URL final
|
|
||||||
header('Location: ' . SITE_URL . '/p/' . urlencode($redirectInfo['finalUrl']));
|
|
||||||
exit;
|
|
||||||
}
|
|
||||||
|
|
||||||
// If there's no redirect or if already at final URL
|
|
||||||
// Se não houver redirecionamento ou se já estiver na URL final
|
|
||||||
// Try to analyze and process the URL
|
|
||||||
// Tenta analisar e processar a URL
|
|
||||||
$content = $analyzer->analyze($url);
|
|
||||||
// Display processed content
|
|
||||||
// Exibe o conteúdo processado
|
|
||||||
echo $content;
|
|
||||||
exit;
|
|
||||||
} catch (URLAnalyzerException $e) {
|
|
||||||
// Get error type and additional info from exception
|
|
||||||
// Obtém o tipo de erro e informações adicionais da exceção
|
|
||||||
$errorType = $e->getErrorType();
|
|
||||||
$additionalInfo = $e->getAdditionalInfo();
|
|
||||||
|
|
||||||
// Handle blocked domain with redirect URL
|
|
||||||
// Trata domínio bloqueado com URL de redirecionamento
|
|
||||||
if ($errorType === URLAnalyzer::ERROR_BLOCKED_DOMAIN && $additionalInfo) {
|
|
||||||
header('Location: ' . trim($additionalInfo) . '?message=' . $errorType);
|
|
||||||
exit;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Redirect to home page with error message
|
|
||||||
// Redireciona para a página inicial com mensagem de erro
|
|
||||||
header('Location: /?message=' . $errorType);
|
|
||||||
exit;
|
|
||||||
} catch (Exception $e) {
|
|
||||||
// Handle any other unexpected errors
|
|
||||||
// Trata quaisquer outros erros inesperados
|
|
||||||
header('Location: /?message=' . URLAnalyzer::ERROR_GENERIC_ERROR);
|
|
||||||
exit;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// Invalid URL / URL inválida
|
|
||||||
header('Location: /?message=' . URLAnalyzer::ERROR_INVALID_URL);
|
|
||||||
exit;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// Invalid path / Path inválido
|
|
||||||
header('Location: /?message=' . URLAnalyzer::ERROR_NOT_FOUND);
|
|
||||||
exit;
|
|
||||||
}
|
|
81
app/pwa.php
81
app/pwa.php
|
@ -1,81 +0,0 @@
|
||||||
<?php
|
|
||||||
/**
|
|
||||||
* PWA Share Target Handler
|
|
||||||
*
|
|
||||||
* This script handles the PWA (Progressive Web App) share target functionality.
|
|
||||||
* It receives a URL parameter via GET request and performs a 301 permanent
|
|
||||||
* redirect to the /p/{URL} endpoint. If no URL is provided, redirects to
|
|
||||||
* the homepage.
|
|
||||||
*
|
|
||||||
* Security measures:
|
|
||||||
* - URL sanitization to prevent XSS attacks
|
|
||||||
* - URL encoding to ensure proper parameter handling
|
|
||||||
*
|
|
||||||
* Este script gerencia a funcionalidade de compartilhamento do PWA (Progressive Web App).
|
|
||||||
* Ele recebe um parâmetro URL via requisição GET e realiza um redirecionamento
|
|
||||||
* permanente 301 para o endpoint /p/{URL}. Se nenhuma URL for fornecida,
|
|
||||||
* redireciona para a página inicial.
|
|
||||||
*
|
|
||||||
* Medidas de segurança:
|
|
||||||
* - Sanitização da URL para prevenir ataques XSS
|
|
||||||
* - Codificação da URL para garantir o correto tratamento dos parâmetros
|
|
||||||
*/
|
|
||||||
|
|
||||||
require_once 'config.php';
|
|
||||||
|
|
||||||
// Get URL and text parameters from GET request
|
|
||||||
// Obtém os parâmetros URL e text da requisição GET
|
|
||||||
$url = $_GET['url'] ?? '';
|
|
||||||
$text = $_GET['text'] ?? '';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Validates if a given URL is valid
|
|
||||||
* Valida se uma URL fornecida é válida
|
|
||||||
*
|
|
||||||
* @param string $url URL to validate / URL para validar
|
|
||||||
* @return bool Returns true if URL is valid, false otherwise / Retorna true se a URL for válida, false caso contrário
|
|
||||||
*/
|
|
||||||
function isValidUrl($url) {
|
|
||||||
// First sanitize the URL
|
|
||||||
// Primeiro sanitiza a URL
|
|
||||||
$sanitized_url = filter_var($url, FILTER_SANITIZE_URL);
|
|
||||||
|
|
||||||
// Then validate it
|
|
||||||
// Então valida
|
|
||||||
return filter_var($sanitized_url, FILTER_VALIDATE_URL) !== false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check URL parameter first
|
|
||||||
// Verifica primeiro o parâmetro URL
|
|
||||||
if (!empty($url) && isValidUrl($url)) {
|
|
||||||
$redirect_url = $url;
|
|
||||||
}
|
|
||||||
// If URL is not valid, check text parameter
|
|
||||||
// Se a URL não é válida, verifica o parâmetro text
|
|
||||||
elseif (!empty($text) && isValidUrl($text)) {
|
|
||||||
$redirect_url = $text;
|
|
||||||
}
|
|
||||||
// If text is not a URL but contains content, try to extract URL from it
|
|
||||||
// Se o texto não é uma URL mas contém conteúdo, tenta extrair URL dele
|
|
||||||
elseif (!empty($text)) {
|
|
||||||
if (preg_match('/https?:\/\/[^\s]+/', $text, $matches)) {
|
|
||||||
$redirect_url = $matches[0];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// If we have a valid URL, redirect to it
|
|
||||||
// Se temos uma URL válida, redireciona para ela
|
|
||||||
if (isset($redirect_url)) {
|
|
||||||
// Sanitize URL to prevent XSS
|
|
||||||
// Sanitiza a URL para prevenir XSS
|
|
||||||
$redirect_url = htmlspecialchars($redirect_url, ENT_QUOTES, 'UTF-8');
|
|
||||||
|
|
||||||
header('HTTP/1.1 301 Moved Permanently');
|
|
||||||
header('Location: /p/' . urlencode($redirect_url));
|
|
||||||
exit;
|
|
||||||
}
|
|
||||||
|
|
||||||
// If no valid URL found in either parameter, redirect to homepage
|
|
||||||
// Se nenhuma URL válida foi encontrada em nenhum dos parâmetros, redireciona para a página inicial
|
|
||||||
header('Location: /');
|
|
||||||
exit;
|
|
179
app/src/Router.php
Normal file
179
app/src/Router.php
Normal file
|
@ -0,0 +1,179 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App;
|
||||||
|
|
||||||
|
require_once __DIR__ . '/../vendor/autoload.php';
|
||||||
|
|
||||||
|
use FastRoute;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Classe Router - Gerenciador de rotas da aplicação
|
||||||
|
* Router Class - Application route manager
|
||||||
|
*
|
||||||
|
* Esta classe implementa o sistema de roteamento usando FastRoute para:
|
||||||
|
* - Gerenciar todas as rotas da aplicação
|
||||||
|
* - Processar requisições HTTP
|
||||||
|
* - Direcionar para os manipuladores apropriados
|
||||||
|
*
|
||||||
|
* This class implements the routing system using FastRoute to:
|
||||||
|
* - Manage all application routes
|
||||||
|
* - Process HTTP requests
|
||||||
|
* - Direct to appropriate handlers
|
||||||
|
*/
|
||||||
|
class Router
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Instância do dispatcher do FastRoute
|
||||||
|
* FastRoute dispatcher instance
|
||||||
|
*/
|
||||||
|
private $dispatcher;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Construtor - Inicializa as rotas da aplicação
|
||||||
|
* Constructor - Initializes application routes
|
||||||
|
*/
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
$this->dispatcher = FastRoute\simpleDispatcher(function(FastRoute\RouteCollector $r) {
|
||||||
|
// Rota principal - página inicial
|
||||||
|
// Main route - home page
|
||||||
|
$r->addRoute('GET', '/', function() {
|
||||||
|
// Inicialização das variáveis para a view principal
|
||||||
|
// Initialize variables for the main view
|
||||||
|
require_once __DIR__ . '/../config.php';
|
||||||
|
require_once __DIR__ . '/../inc/Cache.php';
|
||||||
|
require_once __DIR__ . '/../inc/Language.php';
|
||||||
|
|
||||||
|
\Language::init(LANGUAGE);
|
||||||
|
|
||||||
|
$message = '';
|
||||||
|
$message_type = '';
|
||||||
|
$url = '';
|
||||||
|
|
||||||
|
// Processa mensagens da query string
|
||||||
|
// Process query string messages
|
||||||
|
if (isset($_GET['message'])) {
|
||||||
|
$message_key = $_GET['message'];
|
||||||
|
$messageData = \Language::getMessage($message_key);
|
||||||
|
$message = $messageData['message'];
|
||||||
|
$message_type = $messageData['type'];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Processa submissão do formulário
|
||||||
|
// Process form submission
|
||||||
|
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['url'])) {
|
||||||
|
$url = filter_var($_POST['url'], FILTER_SANITIZE_URL);
|
||||||
|
if (filter_var($url, FILTER_VALIDATE_URL)) {
|
||||||
|
header('Location: ' . SITE_URL . '/p/' . urlencode($url));
|
||||||
|
exit;
|
||||||
|
} else {
|
||||||
|
$messageData = \Language::getMessage('INVALID_URL');
|
||||||
|
$message = $messageData['message'];
|
||||||
|
$message_type = $messageData['type'];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Inicializa o cache para contagem
|
||||||
|
// Initialize cache for counting
|
||||||
|
$cache = new \Cache();
|
||||||
|
$cache_folder = $cache->getCacheFileCount();
|
||||||
|
|
||||||
|
require __DIR__ . '/views/home.php';
|
||||||
|
});
|
||||||
|
|
||||||
|
// Rota da API - inclui api.php existente
|
||||||
|
// API route - includes existing api.php
|
||||||
|
$r->addRoute('GET', '/api/{url:.+}', function($vars) {
|
||||||
|
$_GET['url'] = $vars['url'];
|
||||||
|
require __DIR__ . '/api.php';
|
||||||
|
});
|
||||||
|
|
||||||
|
// Rota da API sem parâmetros - redireciona para raiz
|
||||||
|
// API route without parameters - redirects to root
|
||||||
|
$r->addRoute('GET', '/api[/]', function() {
|
||||||
|
header('Location: /');
|
||||||
|
exit;
|
||||||
|
});
|
||||||
|
|
||||||
|
// Rota de processamento - inclui p.php existente
|
||||||
|
// Processing route - includes existing p.php
|
||||||
|
$r->addRoute('GET', '/p/{url:.+}', function($vars) {
|
||||||
|
$_GET['url'] = $vars['url'];
|
||||||
|
require __DIR__ . '/p.php';
|
||||||
|
});
|
||||||
|
|
||||||
|
// Rota de processamento com query parameter ou sem parâmetros
|
||||||
|
// Processing route with query parameter or without parameters
|
||||||
|
$r->addRoute('GET', '/p[/]', function() {
|
||||||
|
if (isset($_GET['url']) || isset($_GET['text'])) {
|
||||||
|
$url = isset($_GET['url']) ? $_GET['url'] : '';
|
||||||
|
$text = isset($_GET['text']) ? $_GET['text'] : '';
|
||||||
|
|
||||||
|
// Check which parameter is a valid URL
|
||||||
|
if (filter_var($url, FILTER_VALIDATE_URL)) {
|
||||||
|
header('Location: /p/' . urlencode($url));
|
||||||
|
exit;
|
||||||
|
} elseif (filter_var($text, FILTER_VALIDATE_URL)) {
|
||||||
|
header('Location: /p/' . urlencode($text));
|
||||||
|
exit;
|
||||||
|
} else {
|
||||||
|
header('Location: /?message=INVALID_URL');
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
header('Location: /');
|
||||||
|
exit;
|
||||||
|
});
|
||||||
|
|
||||||
|
// Rota do manifesto PWA - inclui manifest.php existente
|
||||||
|
// PWA manifest route - includes existing manifest.php
|
||||||
|
$r->addRoute('GET', '/manifest.json', function() {
|
||||||
|
require __DIR__ . '/views/manifest.php';
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Despacha a requisição para a rota apropriada
|
||||||
|
* Dispatches the request to the appropriate route
|
||||||
|
*/
|
||||||
|
public function dispatch()
|
||||||
|
{
|
||||||
|
$httpMethod = $_SERVER['REQUEST_METHOD'];
|
||||||
|
$uri = $_SERVER['REQUEST_URI'];
|
||||||
|
|
||||||
|
// Remove a query string mas mantém para processamento
|
||||||
|
// Strip query string but keep for processing
|
||||||
|
$queryString = '';
|
||||||
|
if (false !== $pos = strpos($uri, '?')) {
|
||||||
|
$queryString = substr($uri, $pos);
|
||||||
|
$uri = substr($uri, 0, $pos);
|
||||||
|
}
|
||||||
|
$uri = rawurldecode($uri);
|
||||||
|
|
||||||
|
// Parse query string parameters
|
||||||
|
if ($queryString) {
|
||||||
|
parse_str(substr($queryString, 1), $_GET);
|
||||||
|
}
|
||||||
|
|
||||||
|
$routeInfo = $this->dispatcher->dispatch($httpMethod, $uri);
|
||||||
|
|
||||||
|
switch ($routeInfo[0]) {
|
||||||
|
case FastRoute\Dispatcher::NOT_FOUND:
|
||||||
|
require_once __DIR__ . '/../config.php';
|
||||||
|
header('Location: ' . SITE_URL);
|
||||||
|
exit;
|
||||||
|
|
||||||
|
case FastRoute\Dispatcher::METHOD_NOT_ALLOWED:
|
||||||
|
header("HTTP/1.0 405 Method Not Allowed");
|
||||||
|
echo '405 Method Not Allowed';
|
||||||
|
break;
|
||||||
|
|
||||||
|
case FastRoute\Dispatcher::FOUND:
|
||||||
|
$handler = $routeInfo[1];
|
||||||
|
$vars = $routeInfo[2];
|
||||||
|
call_user_func($handler, $vars);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
119
app/src/api.php
Normal file
119
app/src/api.php
Normal file
|
@ -0,0 +1,119 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* URL Analysis API
|
||||||
|
* API para análise de URLs
|
||||||
|
*
|
||||||
|
* This file implements a REST endpoint that receives URLs via GET
|
||||||
|
* and returns processed results in JSON format.
|
||||||
|
*
|
||||||
|
* Este arquivo implementa um endpoint REST que recebe URLs via GET
|
||||||
|
* e retorna resultados processados em formato JSON.
|
||||||
|
*
|
||||||
|
* Features / Funcionalidades:
|
||||||
|
* - URL validation / Validação de URLs
|
||||||
|
* - Content analysis / Análise de conteúdo
|
||||||
|
* - Error handling / Tratamento de erros
|
||||||
|
* - CORS support / Suporte a CORS
|
||||||
|
*/
|
||||||
|
|
||||||
|
require_once __DIR__ . '/../config.php';
|
||||||
|
require_once __DIR__ . '/../inc/URLAnalyzer.php';
|
||||||
|
require_once __DIR__ . '/../inc/Language.php';
|
||||||
|
|
||||||
|
// Initialize language system with default language
|
||||||
|
// Inicializa o sistema de idiomas com o idioma padrão
|
||||||
|
Language::init(LANGUAGE);
|
||||||
|
|
||||||
|
// Set content type as JSON
|
||||||
|
// Define o tipo de conteúdo como JSON
|
||||||
|
header('Content-Type: application/json');
|
||||||
|
|
||||||
|
// Enable CORS (Cross-Origin Resource Sharing)
|
||||||
|
// Habilita CORS (Cross-Origin Resource Sharing)
|
||||||
|
header('Access-Control-Allow-Origin: *');
|
||||||
|
header('Access-Control-Allow-Methods: GET');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function to send standardized JSON response
|
||||||
|
* Função para enviar resposta JSON padronizada
|
||||||
|
*
|
||||||
|
* @param array $data Data to be sent in response / Dados a serem enviados na resposta
|
||||||
|
* @param int $statusCode HTTP status code / Código de status HTTP
|
||||||
|
*/
|
||||||
|
function sendResponse($data, $statusCode = 200)
|
||||||
|
{
|
||||||
|
http_response_code($statusCode);
|
||||||
|
$response = [
|
||||||
|
'status' => $statusCode
|
||||||
|
];
|
||||||
|
|
||||||
|
if (isset($data['error'])) {
|
||||||
|
$response['error'] = $data['error'];
|
||||||
|
} else if (isset($data['url'])) {
|
||||||
|
$response['url'] = $data['url'];
|
||||||
|
}
|
||||||
|
|
||||||
|
echo json_encode($response);
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get URL from Router
|
||||||
|
// Obtém a URL do Router
|
||||||
|
$url = isset($_GET['url']) ? urldecode($_GET['url']) : '';
|
||||||
|
|
||||||
|
// Basic URL validation
|
||||||
|
// Validação básica da URL
|
||||||
|
if (!$url || !filter_var($url, FILTER_VALIDATE_URL)) {
|
||||||
|
sendResponse([
|
||||||
|
'error' => [
|
||||||
|
'type' => URLAnalyzer::ERROR_INVALID_URL,
|
||||||
|
'message' => Language::getMessage('INVALID_URL')['message']
|
||||||
|
]
|
||||||
|
], 400);
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Instantiate URL analyzer
|
||||||
|
// Instancia o analisador de URLs
|
||||||
|
$analyzer = new URLAnalyzer();
|
||||||
|
|
||||||
|
// Try to analyze the provided URL
|
||||||
|
// Tenta analisar a URL fornecida
|
||||||
|
$analyzer->analyze($url);
|
||||||
|
|
||||||
|
// If analysis is successful, return the processed URL
|
||||||
|
// Se a análise for bem-sucedida, retorna a URL processada
|
||||||
|
sendResponse([
|
||||||
|
'url' => SITE_URL . '/p/' . $url
|
||||||
|
], 200);
|
||||||
|
} catch (URLAnalyzerException $e) {
|
||||||
|
// Get error details from the exception
|
||||||
|
// Obtém detalhes do erro da exceção
|
||||||
|
$errorType = $e->getErrorType();
|
||||||
|
$additionalInfo = $e->getAdditionalInfo();
|
||||||
|
|
||||||
|
// Add error header for better client-side handling
|
||||||
|
// Adiciona header de erro para melhor tratamento no cliente
|
||||||
|
header('X-Error-Type: ' . $errorType);
|
||||||
|
if ($additionalInfo) {
|
||||||
|
header('X-Error-Info: ' . $additionalInfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
sendResponse([
|
||||||
|
'error' => [
|
||||||
|
'type' => $errorType,
|
||||||
|
'message' => $e->getMessage(),
|
||||||
|
'details' => $additionalInfo ?: null
|
||||||
|
]
|
||||||
|
], $e->getCode());
|
||||||
|
} catch (Exception $e) {
|
||||||
|
// Handle any other unexpected errors
|
||||||
|
// Trata quaisquer outros erros inesperados
|
||||||
|
sendResponse([
|
||||||
|
'error' => [
|
||||||
|
'type' => URLAnalyzer::ERROR_GENERIC_ERROR,
|
||||||
|
'message' => Language::getMessage('GENERIC_ERROR')['message']
|
||||||
|
]
|
||||||
|
], 500);
|
||||||
|
}
|
88
app/src/p.php
Normal file
88
app/src/p.php
Normal file
|
@ -0,0 +1,88 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* URL Processor
|
||||||
|
* Processador de URLs
|
||||||
|
*
|
||||||
|
* This file is responsible for:
|
||||||
|
* - Receiving URLs through the /p/ path
|
||||||
|
* - Validating URL format
|
||||||
|
* - Processing content using URLAnalyzer
|
||||||
|
* - Displaying processed content or redirecting in case of error
|
||||||
|
*
|
||||||
|
* Este arquivo é responsável por:
|
||||||
|
* - Receber URLs através do path /p/
|
||||||
|
* - Validar o formato da URL
|
||||||
|
* - Processar o conteúdo usando o URLAnalyzer
|
||||||
|
* - Exibir o conteúdo processado ou redirecionar em caso de erro
|
||||||
|
*
|
||||||
|
* Usage examples / Exemplos de uso:
|
||||||
|
* /p/https://exemplo.com
|
||||||
|
* /p/?url=https://exemplo.com
|
||||||
|
*/
|
||||||
|
|
||||||
|
require_once __DIR__ . '/../config.php';
|
||||||
|
require_once __DIR__ . '/../inc/URLAnalyzer.php';
|
||||||
|
|
||||||
|
// Get URL from either path parameter or query string
|
||||||
|
// Obtém a URL do parâmetro de path ou query string
|
||||||
|
$url = '';
|
||||||
|
if (isset($_GET['url'])) {
|
||||||
|
$url = urldecode($_GET['url']);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate URL format
|
||||||
|
// Valida o formato da URL
|
||||||
|
if (filter_var($url, FILTER_VALIDATE_URL)) {
|
||||||
|
$analyzer = new URLAnalyzer();
|
||||||
|
try {
|
||||||
|
// Check for redirects
|
||||||
|
// Verifica se há redirecionamentos
|
||||||
|
$redirectInfo = $analyzer->checkStatus($url);
|
||||||
|
|
||||||
|
// If there's a redirect and the final URL is different
|
||||||
|
// Se houver redirecionamento e a URL final for diferente
|
||||||
|
if ($redirectInfo['hasRedirect'] && $redirectInfo['finalUrl'] !== $url) {
|
||||||
|
// Redirect to final URL
|
||||||
|
// Redireciona para a URL final
|
||||||
|
header('Location: ' . SITE_URL . '/p/' . urlencode($redirectInfo['finalUrl']));
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If there's no redirect or if already at final URL
|
||||||
|
// Se não houver redirecionamento ou se já estiver na URL final
|
||||||
|
// Try to analyze and process the URL
|
||||||
|
// Tenta analisar e processar a URL
|
||||||
|
$content = $analyzer->analyze($url);
|
||||||
|
// Display processed content
|
||||||
|
// Exibe o conteúdo processado
|
||||||
|
echo $content;
|
||||||
|
exit;
|
||||||
|
} catch (URLAnalyzerException $e) {
|
||||||
|
// Get error type and additional info from exception
|
||||||
|
// Obtém o tipo de erro e informações adicionais da exceção
|
||||||
|
$errorType = $e->getErrorType();
|
||||||
|
$additionalInfo = $e->getAdditionalInfo();
|
||||||
|
|
||||||
|
// Handle blocked domain with redirect URL
|
||||||
|
// Trata domínio bloqueado com URL de redirecionamento
|
||||||
|
if ($errorType === URLAnalyzer::ERROR_BLOCKED_DOMAIN && $additionalInfo) {
|
||||||
|
header('Location: ' . trim($additionalInfo) . '?message=' . $errorType);
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Redirect to home page with error message
|
||||||
|
// Redireciona para a página inicial com mensagem de erro
|
||||||
|
header('Location: /?message=' . $errorType);
|
||||||
|
exit;
|
||||||
|
} catch (Exception $e) {
|
||||||
|
// Handle any other unexpected errors
|
||||||
|
// Trata quaisquer outros erros inesperados
|
||||||
|
header('Location: /?message=' . URLAnalyzer::ERROR_GENERIC_ERROR);
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Invalid URL / URL inválida
|
||||||
|
header('Location: /?message=' . URLAnalyzer::ERROR_INVALID_URL);
|
||||||
|
exit;
|
||||||
|
}
|
157
app/src/views/home.php
Normal file
157
app/src/views/home.php
Normal file
|
@ -0,0 +1,157 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="<?php echo Language::getCurrentLanguage(); ?>">
|
||||||
|
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover">
|
||||||
|
<title><?php echo SITE_NAME; ?></title>
|
||||||
|
<link rel="icon" href="<?php echo SITE_URL; ?>/assets/svg/marreta.svg" type="image/svg+xml">
|
||||||
|
<meta name="theme-color" content="#2563eb">
|
||||||
|
<link rel="manifest" href="<?php echo SITE_URL; ?>/manifest.json">
|
||||||
|
|
||||||
|
<!-- PWA meta tags -->
|
||||||
|
<meta name="mobile-web-app-capable" content="yes">
|
||||||
|
<meta name="application-name" content="<?php echo SITE_NAME; ?>">
|
||||||
|
|
||||||
|
<!-- Open Graph meta tags -->
|
||||||
|
<meta property="og:type" content="website" />
|
||||||
|
<meta property="og:url" content="<?php echo SITE_URL; ?>" />
|
||||||
|
<meta property="og:title" content="<?php echo SITE_NAME; ?>" />
|
||||||
|
<meta property="og:description" content="<?php echo htmlspecialchars(SITE_DESCRIPTION); ?>" />
|
||||||
|
<meta property="og:image" content="<?php echo SITE_URL; ?>/assets/opengraph.png" />
|
||||||
|
<script src="https://cdn.tailwindcss.com/3.4.15"></script>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body class="bg-gray-50 min-h-screen">
|
||||||
|
<div class="container mx-auto px-4 py-8 max-w-4xl">
|
||||||
|
<!-- Cabeçalho da página / Page header -->
|
||||||
|
<div class="text-center mb-8">
|
||||||
|
<h1 class="text-4xl font-bold text-gray-800 mb-4">
|
||||||
|
<img src="assets/svg/marreta.svg" class="inline-block w-12 h-12 mb-2" alt="Marreta">
|
||||||
|
<?php echo SITE_NAME; ?>
|
||||||
|
</h1>
|
||||||
|
<p class="text-gray-600 text-lg"><?php echo SITE_DESCRIPTION; ?></p>
|
||||||
|
<p class="text-gray-600 text-lg">
|
||||||
|
<span class="font-bold text-blue-600">
|
||||||
|
<?php echo number_format($cache_folder, 0, ',', '.'); ?>
|
||||||
|
</span>
|
||||||
|
<span><?php echo Language::get('walls_destroyed'); ?></span>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Formulário principal de análise de URLs / Main URL analysis form -->
|
||||||
|
<div class="bg-white rounded-xl shadow-lg p-8 mb-8">
|
||||||
|
<form id="urlForm" method="POST" onsubmit="return validateForm()" class="space-y-6">
|
||||||
|
<div class="relative">
|
||||||
|
<div class="flex items-stretch">
|
||||||
|
<span class="inline-flex items-center px-5 rounded-l-lg border border-r-0 border-gray-300 bg-gray-50 text-gray-500">
|
||||||
|
<img src="assets/svg/link.svg" class="w-6 h-6" alt="Link">
|
||||||
|
</span>
|
||||||
|
<input type="url"
|
||||||
|
name="url"
|
||||||
|
id="url"
|
||||||
|
class="flex-1 block w-full rounded-none rounded-r-lg text-lg py-4 border border-l-0 border-gray-300 bg-gray-50 focus:border-blue-500 focus:ring-blue-500 shadow-sm bg-gray-50"
|
||||||
|
placeholder="<?php echo Language::get('url_placeholder'); ?>"
|
||||||
|
value="<?php echo htmlspecialchars($url); ?>"
|
||||||
|
required
|
||||||
|
pattern="https?://.+"
|
||||||
|
title="<?php echo Language::getMessage('INVALID_URL')['message']; ?>">
|
||||||
|
</div>
|
||||||
|
<button type="submit"
|
||||||
|
class="mt-4 w-full inline-flex justify-center items-center px-6 py-4 border border-transparent text-lg font-medium rounded-lg text-white bg-blue-600 hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500 transition-colors duration-200">
|
||||||
|
<img src="assets/svg/search.svg" class="w-6 h-6 mr-3" alt="Search">
|
||||||
|
<?php echo Language::get('analyze_button'); ?>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
|
||||||
|
<!-- Aviso sobre bloqueadores de anúncios / Ad blocker warning -->
|
||||||
|
<div class="mt-4 text-sm text-gray-600 flex items-start">
|
||||||
|
<p><?php echo str_replace('{site_name}', SITE_NAME, Language::get('adblocker_warning')); ?></p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Área de mensagens de erro/alerta / Error/warning message area -->
|
||||||
|
<?php if ($message): ?>
|
||||||
|
<div class="mt-6 <?php echo $message_type === 'error' ? 'bg-red-50 border-red-400' : 'bg-yellow-50 border-yellow-400'; ?> border-l-4 p-4 rounded-r">
|
||||||
|
<div class="flex">
|
||||||
|
<div class="flex-shrink-0">
|
||||||
|
<?php if ($message_type === 'error'): ?>
|
||||||
|
<img src="assets/svg/error.svg" class="w-6 h-6" alt="Error">
|
||||||
|
<?php else: ?>
|
||||||
|
<img src="assets/svg/warning.svg" class="w-6 h-6" alt="Warning">
|
||||||
|
<?php endif; ?>
|
||||||
|
</div>
|
||||||
|
<div class="ml-3">
|
||||||
|
<p class="text-base <?php echo $message_type === 'error' ? 'text-red-700' : 'text-yellow-700'; ?>">
|
||||||
|
<?php echo htmlspecialchars($message); ?>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<?php endif; ?>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Adicionar como aplicativo / Add as app (mobile only) -->
|
||||||
|
<div class="bg-white rounded-xl shadow-lg p-8 mt-8 mb-8 md:hidden">
|
||||||
|
<h2 class="text-xl font-semibold text-gray-800 mb-6 flex items-center">
|
||||||
|
<img src="assets/svg/marreta.svg" class="w-6 h-6 mr-3" alt="App">
|
||||||
|
<?php echo Language::get('add_as_app'); ?>
|
||||||
|
</h2>
|
||||||
|
<div class="space-y-4">
|
||||||
|
<p class="text-gray-600">
|
||||||
|
<?php echo str_replace('{site_name}', SITE_NAME, Language::get('add_as_app_description')); ?>
|
||||||
|
</p>
|
||||||
|
<div class="bg-gray-50 rounded-lg p-4">
|
||||||
|
<ol class="list-decimal list-inside space-y-2 text-gray-700">
|
||||||
|
<li><?php echo Language::get('add_as_app_step1'); ?></li>
|
||||||
|
<li><?php echo Language::get('add_as_app_step2'); ?></li>
|
||||||
|
<li><?php echo Language::get('add_as_app_step3'); ?></li>
|
||||||
|
<li><?php echo str_replace('{site_name}', SITE_NAME, Language::get('add_as_app_step4')); ?></li>
|
||||||
|
</ol>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Seção de Bookmarklet / Bookmarklet section (desktop only) -->
|
||||||
|
<div class="bg-white rounded-xl shadow-lg p-8 mt-8 mb-8 hidden md:block">
|
||||||
|
<h2 class="text-xl font-semibold text-gray-800 mb-6 flex items-center">
|
||||||
|
<img src="assets/svg/bookmark.svg" class="w-6 h-6 mr-3" alt="Favoritos">
|
||||||
|
<?php echo Language::get('bookmarklet_title'); ?>
|
||||||
|
</h2>
|
||||||
|
<div class="space-y-4">
|
||||||
|
<p class="text-gray-600">
|
||||||
|
<?php echo str_replace('{site_name}', SITE_NAME, Language::get('bookmarklet_description')); ?>
|
||||||
|
</p>
|
||||||
|
<div class="flex justify-center">
|
||||||
|
<a href="javascript:(function(){let currentUrl=window.location.href;window.location.href='<?php echo SITE_URL; ?>/p/'+encodeURIComponent(currentUrl);})()"
|
||||||
|
class="inline-flex items-center px-6 py-3 border-2 border-blue-500 font-medium rounded-lg text-blue-600 bg-white hover:bg-blue-50 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500 transition-colors duration-200 cursor-move"
|
||||||
|
onclick="return false;">
|
||||||
|
<img src="assets/svg/marreta.svg" class="w-5 h-5 mr-2" alt="Marreta">
|
||||||
|
<?php echo str_replace('{site_name}', SITE_NAME, Language::get('open_in')); ?>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="text-gray-600 text-center text-sm">
|
||||||
|
<p>
|
||||||
|
<?php echo Language::get('open_source_description'); ?>
|
||||||
|
</p>
|
||||||
|
<p class="mt-2">
|
||||||
|
<a href="https://github.com/manualdousuario/marreta/wiki/API-Rest" target="_blank" class="underline">API Rest</a> ● <a href="https://github.com/manualdousuario/marreta/" target="_blank" class="underline">Github</a>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Scripts JavaScript -->
|
||||||
|
<script>
|
||||||
|
<?php
|
||||||
|
$js_file = 'assets/js/scripts.js';
|
||||||
|
if (file_exists($js_file)) {
|
||||||
|
echo file_get_contents($js_file);
|
||||||
|
}
|
||||||
|
?>
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -9,8 +9,8 @@
|
||||||
* Ele define o comportamento da aplicação quando instalada em um dispositivo e sua aparência.
|
* Ele define o comportamento da aplicação quando instalada em um dispositivo e sua aparência.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
require_once 'config.php';
|
require_once __DIR__ . '/../../config.php';
|
||||||
require_once 'inc/Language.php';
|
require_once __DIR__ . '/../../inc/Language.php';
|
||||||
|
|
||||||
header('Content-Type: application/json');
|
header('Content-Type: application/json');
|
||||||
|
|
14
default.conf
14
default.conf
|
@ -48,18 +48,10 @@ server {
|
||||||
return 403;
|
return 403;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# All requests go through index.php for FastRoute routing
|
||||||
|
# Todas as requisições passam pelo index.php para roteamento FastRoute
|
||||||
location / {
|
location / {
|
||||||
try_files $uri $uri/ $uri/index.php?$args;
|
try_files $uri $uri/ /index.php?$args;
|
||||||
}
|
|
||||||
|
|
||||||
location ~ ^/(api|p)/ {
|
|
||||||
try_files $uri $uri/ /$1.php;
|
|
||||||
}
|
|
||||||
|
|
||||||
# Serve manifest.json from manifest.php
|
|
||||||
# Serve manifest.json a partir do manifest.php
|
|
||||||
location = /manifest.json {
|
|
||||||
rewrite ^ /manifest.php last;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
location ~ \.php$ {
|
location ~ \.php$ {
|
||||||
|
|
Loading…
Add table
Reference in a new issue