mirror of
https://github.com/manualdousuario/marreta.git
synced 2025-09-01 10:10:14 +00:00
traduções de documentações
This commit is contained in:
parent
55ac7fe018
commit
a97966c1b4
16 changed files with 514 additions and 181 deletions
|
@ -1,5 +1,6 @@
|
|||
FROM php:8.3-fpm
|
||||
|
||||
# Install PHP dependencies and extensions
|
||||
# Instala dependências e extensões do PHP
|
||||
RUN apt-get update && apt-get install -y \
|
||||
nginx \
|
||||
|
@ -14,12 +15,15 @@ RUN apt-get update && apt-get install -y \
|
|||
&& pecl install redis \
|
||||
&& docker-php-ext-enable redis opcache
|
||||
|
||||
# Copy OPCache configuration
|
||||
# Copia a configuração do OPCache
|
||||
COPY opcache.ini /usr/local/etc/php/conf.d/opcache.ini
|
||||
|
||||
# Install Composer
|
||||
# Instala o Composer
|
||||
RUN curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer
|
||||
|
||||
# Copy webservice configuration
|
||||
# Copia a configuração do webservice
|
||||
COPY default.conf /etc/nginx/sites-available/default
|
||||
|
||||
|
@ -29,12 +33,14 @@ COPY app/ /app/
|
|||
WORKDIR /app
|
||||
RUN composer install --no-interaction --optimize-autoloader
|
||||
|
||||
# Copy and configure initialization script permissions
|
||||
# Copia e configura permissões do script de inicialização
|
||||
COPY docker-entrypoint.sh /usr/local/bin/
|
||||
RUN chmod +x /usr/local/bin/docker-entrypoint.sh
|
||||
|
||||
RUN mkdir -p /app/cache /app/logs
|
||||
|
||||
# Configure base permissions for /app directory
|
||||
# Configura permissões base para o diretório /app
|
||||
RUN chown -R www-data:www-data /app \
|
||||
&& chmod -R 755 /app
|
||||
|
|
57
app/api.php
57
app/api.php
|
@ -1,28 +1,40 @@
|
|||
<?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.
|
||||
*
|
||||
* Funcionalidades:
|
||||
* - Validação de URLs
|
||||
* - Análise de conteúdo
|
||||
* - Tratamento de erros
|
||||
* - Suporte a CORS
|
||||
* 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/';
|
||||
|
@ -31,10 +43,11 @@ 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 Dados a serem enviados na resposta
|
||||
* @param int $statusCode Código de status HTTP
|
||||
* @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)
|
||||
{
|
||||
|
@ -53,58 +66,72 @@ if (strpos($path, $prefix) === 0) {
|
|||
exit;
|
||||
}
|
||||
|
||||
// Basic URL validation
|
||||
// Validação básica da URL
|
||||
if (!$url || !filter_var($url, FILTER_VALIDATE_URL)) {
|
||||
$errorMessage = Language::getMessage('INVALID_URL');
|
||||
sendResponse([
|
||||
'error' => [
|
||||
'code' => 'INVALID_URL',
|
||||
'message' => MESSAGES['INVALID_URL']['message']
|
||||
'message' => $errorMessage['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 (Exception $e) {
|
||||
// Error handling with mapping to appropriate HTTP codes
|
||||
// Tratamento de erros com mapeamento para códigos HTTP apropriados
|
||||
$message = $e->getMessage();
|
||||
$statusCode = 400;
|
||||
$errorCode = 'GENERIC_ERROR';
|
||||
$errorMessage = Language::getMessage('GENERIC_ERROR');
|
||||
|
||||
// Mapeia a mensagem de erro para o código e status apropriados
|
||||
foreach (MESSAGES as $key => $value) {
|
||||
if (strpos($message, $value['message']) !== false) {
|
||||
$statusCode = ($value['type'] === 'error') ? 400 : 503;
|
||||
$errorCode = $key;
|
||||
// Try to match the error message with known error types
|
||||
// Tenta corresponder a mensagem de erro com tipos de erro conhecidos
|
||||
$errorTypes = ['BLOCKED_DOMAIN', 'DNS_FAILURE', 'HTTP_ERROR', 'CONNECTION_ERROR', 'CONTENT_ERROR'];
|
||||
foreach ($errorTypes as $type) {
|
||||
$typeMessage = Language::getMessage($type);
|
||||
if (strpos($message, $typeMessage['message']) !== false) {
|
||||
$statusCode = ($typeMessage['type'] === 'error') ? 400 : 503;
|
||||
$errorCode = $type;
|
||||
$errorMessage = $typeMessage;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Add error header for better client-side handling
|
||||
// Adiciona header de erro para melhor tratamento no cliente
|
||||
header('X-Error-Message: ' . $message);
|
||||
|
||||
sendResponse([
|
||||
'error' => [
|
||||
'code' => $errorCode,
|
||||
'message' => $message
|
||||
'message' => $errorMessage['message']
|
||||
]
|
||||
], $statusCode);
|
||||
}
|
||||
} else {
|
||||
// Return 404 error for endpoints not found
|
||||
// Retorna erro 404 para endpoints não encontrados
|
||||
$errorMessage = Language::getMessage('NOT_FOUND');
|
||||
sendResponse([
|
||||
'error' => [
|
||||
'code' => 'NOT_FOUND',
|
||||
'message' => MESSAGES['NOT_FOUND']['message']
|
||||
'message' => $errorMessage['message']
|
||||
]
|
||||
], 404);
|
||||
}
|
||||
|
|
|
@ -1,14 +1,18 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* List of blocked domains
|
||||
* Lista de domínios bloqueados
|
||||
*
|
||||
* Defines domains that cannot be accessed by the system
|
||||
* due to usage policies or technical restrictions
|
||||
*
|
||||
* Define os domínios que não podem ser acessados pelo sistema
|
||||
* por questões de política de uso ou restrições técnicas
|
||||
*/
|
||||
return [
|
||||
// Sites de notícias
|
||||
//-- Conteudo fica atras de um acesso de login
|
||||
// News sites / Sites de notícias
|
||||
//-- Content behind login access / Conteúdo fica atrás de um acesso de login
|
||||
'wsj.com',
|
||||
'piaui.folha.uol.com.br',
|
||||
'economist.com',
|
||||
|
@ -25,14 +29,14 @@ return [
|
|||
'adage.com',
|
||||
'couriermail.com.au',
|
||||
'mittelbayerische.de/',
|
||||
//-- Bloqueio tecnico de acesso ao conteudo
|
||||
//-- Technical access blocking / Bloqueio técnico de acesso ao conteúdo
|
||||
'bloomberg.com',
|
||||
'sportskeeda.com',
|
||||
'kansascity.com',
|
||||
'fastcompany.com',
|
||||
'expressnews.com',
|
||||
'nydailynews.com',
|
||||
// Tracking
|
||||
// Tracking services / Serviços de rastreamento
|
||||
'metaffiliation.com',
|
||||
'google-analytics.com',
|
||||
'googletagmanager.com',
|
||||
|
@ -53,7 +57,7 @@ return [
|
|||
'fullstory.com',
|
||||
'heap.io',
|
||||
'clearbrain.com',
|
||||
// Redes sociais
|
||||
// Social networks / Redes sociais
|
||||
'facebook.com',
|
||||
'instagram.com',
|
||||
'twitter.com',
|
||||
|
@ -67,7 +71,7 @@ return [
|
|||
'redd.it',
|
||||
'bsky.app',
|
||||
'threads.net',
|
||||
// Streaming
|
||||
// Streaming services / Serviços de streaming
|
||||
'netflix.com',
|
||||
'hulu.com',
|
||||
'disneyplus.com',
|
||||
|
@ -75,32 +79,32 @@ return [
|
|||
'spotify.com',
|
||||
'youtube.com',
|
||||
'twitch.tv',
|
||||
// E-commerce
|
||||
// E-commerce sites / Sites de comércio eletrônico
|
||||
'amazon.com',
|
||||
'ebay.com',
|
||||
'aliexpress.com',
|
||||
'mercadolivre.com.br',
|
||||
'shopify.com',
|
||||
// Compartilhamento de arquivos
|
||||
// File sharing / Compartilhamento de arquivos
|
||||
'mega.nz',
|
||||
'mediafire.com',
|
||||
'wetransfer.com',
|
||||
'dropbox.com',
|
||||
'torrent9.pe',
|
||||
'thepiratebay.org',
|
||||
// Sites adultos
|
||||
// Adult sites / Sites adultos
|
||||
'pornhub.com',
|
||||
'xvideos.com',
|
||||
'xnxx.com',
|
||||
'onlyfans.com',
|
||||
'privacy.com.br',
|
||||
'fatalmodel.com',
|
||||
// Apostas e jogos
|
||||
// Betting and gaming / Apostas e jogos
|
||||
'bet365.com',
|
||||
'betfair.com',
|
||||
'pokerstars.com',
|
||||
'casino.com',
|
||||
// Outros sites populares
|
||||
// Other popular sites / Outros sites populares
|
||||
'github.com',
|
||||
'stackoverflow.com',
|
||||
'wikipedia.org',
|
||||
|
|
|
@ -1,28 +1,32 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* Specific rule configurations for individual domains
|
||||
* Configurações específicas de regras para domínios individuais
|
||||
*
|
||||
* This file contains custom rules for specific sites, allowing
|
||||
* system behavior adjustment for each domain individually.
|
||||
*
|
||||
* Este arquivo contém regras personalizadas para sites específicos, permitindo
|
||||
* ajustar o comportamento do sistema para cada domínio individualmente.
|
||||
*
|
||||
* Estrutura das regras por domínio:
|
||||
* - userAgent: Define um User-Agent personalizado para o domínio
|
||||
* - headers: Headers HTTP personalizados para requisições
|
||||
* - idElementRemove: Array de IDs HTML que devem ser removidos da página
|
||||
* - classElementRemove: Array de classes HTML que devem ser removidas
|
||||
* - scriptTagRemove: Array de scripts que devem ser removidos (partial match)
|
||||
* - cookies: Array associativo de cookies a serem definidos (null remove o cookie)
|
||||
* - classAttrRemove: Array de classes a serem removidas de elementos
|
||||
* - customCode: String contendo código JavaScript personalizado para execução
|
||||
* - customStyle: String contendo código CSS personalizado para execução
|
||||
* - excludeGlobalRules: Array associativo de regras globais a serem excluídas para este domínio
|
||||
* Exemplo:
|
||||
* Domain rule structure / Estrutura das regras por domínio:
|
||||
* - userAgent: Define custom User-Agent for the domain / Define um User-Agent personalizado para o domínio
|
||||
* - headers: Custom HTTP headers for requests / Headers HTTP personalizados para requisições
|
||||
* - idElementRemove: Array of HTML IDs to be removed / Array de IDs HTML que devem ser removidos da página
|
||||
* - classElementRemove: Array of HTML classes to be removed / Array de classes HTML que devem ser removidas
|
||||
* - scriptTagRemove: Array of scripts to be removed (partial match) / Array de scripts que devem ser removidos (partial match)
|
||||
* - cookies: Associative array of cookies to be set (null removes cookie) / Array associativo de cookies a serem definidos (null remove o cookie)
|
||||
* - classAttrRemove: Array of classes to be removed from elements / Array de classes a serem removidas de elementos
|
||||
* - customCode: String containing custom JavaScript code / String contendo código JavaScript personalizado
|
||||
* - customStyle: String containing custom CSS code / String contendo código CSS personalizado
|
||||
* - excludeGlobalRules: Associative array of global rules to exclude for this domain / Array associativo de regras globais a serem excluídas para este domínio
|
||||
* Example / Exemplo:
|
||||
* 'excludeGlobalRules' => [
|
||||
* 'scriptTagRemove' => ['gtm.js', 'ga.js'], // Exclui scripts específicos das regras globais
|
||||
* 'classElementRemove' => ['subscription'] // Exclui classes específicas das regras globais
|
||||
* 'scriptTagRemove' => ['gtm.js', 'ga.js'], // Excludes specific scripts from global rules / Exclui scripts específicos das regras globais
|
||||
* 'classElementRemove' => ['subscription'] // Excludes specific classes from global rules / Exclui classes específicas das regras globais
|
||||
* ]
|
||||
* - useSelenium: Boolean indicando se deve usar Selenium para extração
|
||||
* - useSelenium: Boolean indicating whether to use Selenium for extraction / Boolean indicando se deve usar Selenium para extração
|
||||
*/
|
||||
return [
|
||||
'nsctotal.com.br' => [
|
||||
|
|
|
@ -1,15 +1,24 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* Global rule configurations applied to all domains
|
||||
* Configurações globais de regras aplicadas a todos os domínios
|
||||
*
|
||||
* This file defines rules that are applied by default to all sites,
|
||||
* organized into categories for better maintenance and understanding.
|
||||
*
|
||||
* Este arquivo define regras que são aplicadas por padrão a todos os sites,
|
||||
* organizadas em categorias para melhor manutenção e compreensão.
|
||||
*
|
||||
* Note: These rules can be overridden or disabled for specific domains
|
||||
* using the 'excludeGlobalRules' configuration in domain_rules.php
|
||||
*
|
||||
* Nota: Estas regras podem ser sobrescritas ou desativadas para domínios específicos
|
||||
* usando a configuração 'excludeGlobalRules' em domain_rules.php
|
||||
*/
|
||||
return [
|
||||
// HTML classes to be removed from all pages
|
||||
// Classes HTML a serem removidas de todas as páginas
|
||||
'classElementRemove' => [
|
||||
'subscription',
|
||||
'subscriber-content',
|
||||
|
@ -31,6 +40,8 @@ return [
|
|||
'signup-overlay',
|
||||
'onesignal-slidedown-container'
|
||||
],
|
||||
// Scripts to be removed from all pages
|
||||
// Scripts a serem removidos de todas as páginas
|
||||
'scriptTagRemove' => [
|
||||
'gtm.js',
|
||||
'ga.js',
|
||||
|
|
|
@ -1,12 +1,25 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* Bot configurations
|
||||
* Configurações dos bots
|
||||
*
|
||||
* Defines user agents that can be used to make requests
|
||||
* Define os user agents que podem ser utilizados para fazer requisições
|
||||
*
|
||||
* These user agents are used to simulate legitimate web crawlers
|
||||
* Estes user agents são usados para simular crawlers web legítimos
|
||||
*/
|
||||
return [
|
||||
// Google News bot
|
||||
// Bot do Google News
|
||||
'Googlebot-News',
|
||||
|
||||
// Mobile Googlebot
|
||||
// Googlebot para dispositivos móveis
|
||||
'Mozilla/5.0 (Linux; Android 6.0.1; Nexus 5X Build/MMB29P) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/W.X.Y.Z Mobile Safari/537.36 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)',
|
||||
|
||||
// Desktop Googlebot
|
||||
// Googlebot para desktop
|
||||
'Mozilla/5.0 AppleWebKit/537.36 (KHTML, like Gecko; compatible; Googlebot/2.1; +http://www.google.com/bot.html) Chrome/W.X.Y.Z Safari/537.36'
|
||||
];
|
||||
|
|
|
@ -6,8 +6,14 @@ use Inc\Cache\S3Storage;
|
|||
use Inc\Cache\RedisStorage;
|
||||
|
||||
/**
|
||||
* Class responsible for system cache management
|
||||
* Classe responsável pelo gerenciamento de cache do sistema
|
||||
*
|
||||
* This class implements functionalities to store and retrieve
|
||||
* cached content, supporting multiple storage backends (disk or S3).
|
||||
* The cache is organized by URLs converted to unique IDs using SHA-256.
|
||||
* Content is compressed using gzip to save space.
|
||||
*
|
||||
* Esta classe implementa funcionalidades para armazenar e recuperar
|
||||
* conteúdo em cache, suportando múltiplos backends de armazenamento (disco ou S3).
|
||||
* O cache é organizado por URLs convertidas em IDs únicos usando SHA-256.
|
||||
|
@ -16,25 +22,31 @@ use Inc\Cache\RedisStorage;
|
|||
class Cache
|
||||
{
|
||||
/**
|
||||
* @var CacheStorageInterface Storage implementation for cache
|
||||
* @var CacheStorageInterface Implementação de storage para o cache
|
||||
*/
|
||||
private $storage;
|
||||
|
||||
/**
|
||||
* @var RedisStorage Redis instance for file counting
|
||||
* @var RedisStorage Instância do Redis para contagem de arquivos
|
||||
*/
|
||||
private $redisStorage;
|
||||
|
||||
/**
|
||||
* Class constructor
|
||||
* Construtor da classe
|
||||
*
|
||||
* Initializes appropriate storage based on configuration
|
||||
* Inicializa o storage apropriado baseado na configuração
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
// Initialize RedisStorage for file counting
|
||||
// Inicializa o RedisStorage para contagem de arquivos
|
||||
$this->redisStorage = new RedisStorage(CACHE_DIR);
|
||||
|
||||
// If S3 is configured and active, use S3Storage
|
||||
// Se S3 está configurado e ativo, usa S3Storage
|
||||
if (defined('S3_CACHE_ENABLED') && S3_CACHE_ENABLED === true) {
|
||||
$this->storage = new S3Storage([
|
||||
|
@ -47,15 +59,17 @@ class Cache
|
|||
'endpoint' => defined('S3_ENDPOINT') ? S3_ENDPOINT : null
|
||||
]);
|
||||
} else {
|
||||
// Otherwise, use disk storage
|
||||
// Caso contrário, usa o storage em disco
|
||||
$this->storage = new DiskStorage(CACHE_DIR);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the count of cached files
|
||||
* Obtém a contagem de arquivos em cache
|
||||
*
|
||||
* @return int Número de arquivos em cache
|
||||
* @return int Number of files in cache / Número de arquivos em cache
|
||||
*/
|
||||
public function getCacheFileCount(): int
|
||||
{
|
||||
|
@ -63,27 +77,32 @@ class Cache
|
|||
}
|
||||
|
||||
/**
|
||||
* Generates a unique ID for a URL
|
||||
* Gera um ID único para uma URL
|
||||
*
|
||||
* @param string $url URL para qual será gerado o ID
|
||||
* @return string Hash SHA-256 da URL normalizada
|
||||
* @param string $url URL for which the ID will be generated / URL para qual será gerado o ID
|
||||
* @return string SHA-256 hash of the normalized URL / Hash SHA-256 da URL normalizada
|
||||
*/
|
||||
public function generateId($url)
|
||||
{
|
||||
// Remove protocol and www
|
||||
// Remove protocolo e www
|
||||
$url = preg_replace('#^https?://(www\.)?#', '', $url);
|
||||
// Generate unique ID using SHA-256
|
||||
// Gera ID único usando SHA-256
|
||||
return hash('sha256', $url);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if cache exists for a given URL
|
||||
* Verifica se existe cache para uma determinada URL
|
||||
*
|
||||
* @param string $url URL a ser verificada
|
||||
* @return bool True se existir cache, False caso contrário
|
||||
* @param string $url URL to check / URL a ser verificada
|
||||
* @return bool True if cache exists, False otherwise / True se existir cache, False caso contrário
|
||||
*/
|
||||
public function exists($url)
|
||||
{
|
||||
// If DISABLE_CACHE is active, always return false
|
||||
// Se DISABLE_CACHE está ativo, sempre retorna false
|
||||
if (DISABLE_CACHE) {
|
||||
return false;
|
||||
|
@ -93,13 +112,15 @@ class Cache
|
|||
}
|
||||
|
||||
/**
|
||||
* Retrieves cached content for a URL
|
||||
* Recupera o conteúdo em cache de uma URL
|
||||
*
|
||||
* @param string $url URL do conteúdo a ser recuperado
|
||||
* @return string|null Conteúdo em cache ou null se não existir
|
||||
* @param string $url URL of the content to retrieve / URL do conteúdo a ser recuperado
|
||||
* @return string|null Cached content or null if it doesn't exist / Conteúdo em cache ou null se não existir
|
||||
*/
|
||||
public function get($url)
|
||||
{
|
||||
// If DISABLE_CACHE is active, always return null
|
||||
// Se DISABLE_CACHE está ativo, sempre retorna null
|
||||
if (DISABLE_CACHE) {
|
||||
return null;
|
||||
|
@ -109,14 +130,16 @@ class Cache
|
|||
}
|
||||
|
||||
/**
|
||||
* Stores content in cache for a URL
|
||||
* Armazena conteúdo em cache para uma URL
|
||||
*
|
||||
* @param string $url URL associada ao conteúdo
|
||||
* @param string $content Conteúdo a ser armazenado em cache
|
||||
* @return bool True se o cache foi salvo com sucesso, False caso contrário
|
||||
* @param string $url URL associated with the content / URL associada ao conteúdo
|
||||
* @param string $content Content to be cached / Conteúdo a ser armazenado em cache
|
||||
* @return bool True if cache was saved successfully, False otherwise / True se o cache foi salvo com sucesso, False caso contrário
|
||||
*/
|
||||
public function set($url, $content)
|
||||
{
|
||||
// If DISABLE_CACHE is active, don't generate cache
|
||||
// Se DISABLE_CACHE está ativo, não gera cache
|
||||
if (DISABLE_CACHE) {
|
||||
return true;
|
||||
|
|
|
@ -2,30 +2,40 @@
|
|||
|
||||
namespace Inc\Cache;
|
||||
|
||||
/**
|
||||
* Interface for cache storage implementations
|
||||
* Interface para implementações de armazenamento de cache
|
||||
*
|
||||
* This interface defines the required methods for any cache storage implementation.
|
||||
* Esta interface define os métodos necessários para qualquer implementação de armazenamento de cache.
|
||||
*/
|
||||
interface CacheStorageInterface
|
||||
{
|
||||
/**
|
||||
* Checks if cache exists for a given ID
|
||||
* Verifica se existe cache para um determinado ID
|
||||
*
|
||||
* @param string $id ID do cache
|
||||
* @return bool
|
||||
* @param string $id Cache ID / ID do cache
|
||||
* @return bool True if cache exists, false otherwise / True se o cache existir, false caso contrário
|
||||
*/
|
||||
public function exists(string $id): bool;
|
||||
|
||||
/**
|
||||
* Retrieves cached content
|
||||
* Recupera o conteúdo em cache
|
||||
*
|
||||
* @param string $id ID do cache
|
||||
* @return string|null
|
||||
* @param string $id Cache ID / ID do cache
|
||||
* @return string|null Cached content or null if not found / Conteúdo em cache ou null se não encontrado
|
||||
*/
|
||||
public function get(string $id): ?string;
|
||||
|
||||
/**
|
||||
* Stores content in cache
|
||||
* Armazena conteúdo em cache
|
||||
*
|
||||
* @param string $id ID do cache
|
||||
* @param string $content Conteúdo a ser armazenado
|
||||
* @return bool
|
||||
* @param string $id Cache ID / ID do cache
|
||||
* @param string $content Content to be stored / Conteúdo a ser armazenado
|
||||
* @return bool True if successful, false otherwise / True se bem sucedido, false caso contrário
|
||||
*/
|
||||
public function set(string $id, string $content): bool;
|
||||
}
|
||||
|
|
|
@ -2,17 +2,26 @@
|
|||
|
||||
namespace Inc\Cache;
|
||||
|
||||
/**
|
||||
* Disk-based cache storage implementation
|
||||
* Implementação de armazenamento de cache em disco
|
||||
*
|
||||
* This class implements file-based caching using gzip compression
|
||||
* Esta classe implementa cache baseado em arquivos usando compressão gzip
|
||||
*/
|
||||
class DiskStorage implements CacheStorageInterface
|
||||
{
|
||||
/**
|
||||
* @var string Directory where cache files will be stored
|
||||
* @var string Diretório onde os arquivos de cache serão armazenados
|
||||
*/
|
||||
private $cacheDir;
|
||||
|
||||
/**
|
||||
* Class constructor
|
||||
* Construtor da classe
|
||||
*
|
||||
* @param string $cacheDir Diretório base para armazenamento do cache
|
||||
* @param string $cacheDir Base directory for cache storage / Diretório base para armazenamento do cache
|
||||
*/
|
||||
public function __construct(string $cacheDir)
|
||||
{
|
||||
|
@ -23,7 +32,11 @@ class DiskStorage implements CacheStorageInterface
|
|||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
* Checks if cache exists for a given ID
|
||||
* Verifica se existe cache para um determinado ID
|
||||
*
|
||||
* @param string $id Cache ID / ID do cache
|
||||
* @return bool True if cache exists, false otherwise / True se o cache existir, false caso contrário
|
||||
*/
|
||||
public function exists(string $id): bool
|
||||
{
|
||||
|
@ -32,7 +45,11 @@ class DiskStorage implements CacheStorageInterface
|
|||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
* Retrieves cached content
|
||||
* Recupera o conteúdo em cache
|
||||
*
|
||||
* @param string $id Cache ID / ID do cache
|
||||
* @return string|null Cached content or null if not found / Conteúdo em cache ou null se não encontrado
|
||||
*/
|
||||
public function get(string $id): ?string
|
||||
{
|
||||
|
@ -51,7 +68,12 @@ class DiskStorage implements CacheStorageInterface
|
|||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
* Stores content in cache
|
||||
* Armazena conteúdo em cache
|
||||
*
|
||||
* @param string $id Cache ID / ID do cache
|
||||
* @param string $content Content to be stored / Conteúdo a ser armazenado
|
||||
* @return bool True if successful, false otherwise / True se bem sucedido, false caso contrário
|
||||
*/
|
||||
public function set(string $id, string $content): bool
|
||||
{
|
||||
|
|
|
@ -2,60 +2,82 @@
|
|||
|
||||
namespace Inc\Cache;
|
||||
|
||||
/**
|
||||
* Redis-based cache storage implementation
|
||||
* Implementação de armazenamento de cache baseado em Redis
|
||||
*
|
||||
* This class provides cache storage and file counting functionality using Redis
|
||||
* Esta classe fornece armazenamento de cache e funcionalidade de contagem de arquivos usando Redis
|
||||
*
|
||||
* @property \Redis|null $redis Redis client instance
|
||||
*/
|
||||
class RedisStorage implements CacheStorageInterface
|
||||
{
|
||||
/**
|
||||
* @var \Redis|null Redis client instance
|
||||
* @var \Redis|null Instância do cliente Redis
|
||||
*/
|
||||
private $redis;
|
||||
|
||||
/**
|
||||
* @var string Cache directory for file counting
|
||||
* @var string Diretório de cache para contagem de arquivos
|
||||
*/
|
||||
private $cacheDir;
|
||||
|
||||
/**
|
||||
* Class constructor
|
||||
* Construtor da classe
|
||||
*
|
||||
* @param string $cacheDir Diretório base para armazenamento do cache
|
||||
* @param string $cacheDir Base directory for cache storage / Diretório base para armazenamento do cache
|
||||
*/
|
||||
public function __construct(string $cacheDir)
|
||||
{
|
||||
$this->cacheDir = $cacheDir;
|
||||
|
||||
// Try to initialize Redis connection
|
||||
// Tenta inicializar conexão Redis
|
||||
try {
|
||||
/** @var \Redis $redis */
|
||||
$this->redis = new \Redis();
|
||||
$this->redis->connect(REDIS_HOST, REDIS_PORT, 2.5);
|
||||
$this->redis->setOption(\Redis::OPT_PREFIX, REDIS_PREFIX);
|
||||
} catch (\Exception $e) {
|
||||
// If it fails, set redis to null
|
||||
// Se falhar, define redis como null
|
||||
$this->redis = null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Counts the number of files in the cache directory
|
||||
* Conta o número de arquivos no diretório de cache
|
||||
*
|
||||
* @return int Número de arquivos no diretório de cache
|
||||
* @return int Number of files in the cache directory / Número de arquivos no diretório de cache
|
||||
*/
|
||||
public function countCacheFiles(): int
|
||||
{
|
||||
// Key to store file count in Redis
|
||||
// Chave para armazenar a contagem de arquivos no Redis
|
||||
$cacheCountKey = 'cache_file_count';
|
||||
|
||||
// If Redis is available
|
||||
// Se Redis estiver disponível
|
||||
if ($this->redis !== null) {
|
||||
// Check if the key exists and has a value
|
||||
// Verifica se a chave existe e tem valor
|
||||
/** @var string|false $cachedCount */
|
||||
$cachedCount = $this->redis->get($cacheCountKey);
|
||||
if ($cachedCount !== false) {
|
||||
return (int)$cachedCount;
|
||||
}
|
||||
}
|
||||
|
||||
// If Redis is not available or key is empty, count files
|
||||
// Se Redis não estiver disponível ou chave vazia, conta os arquivos
|
||||
$fileCount = iterator_count(new \FilesystemIterator($this->cacheDir));
|
||||
|
||||
// If Redis is available, save the count
|
||||
// Se Redis estiver disponível, salva a contagem
|
||||
if ($this->redis !== null) {
|
||||
$this->redis->set($cacheCountKey, $fileCount);
|
||||
|
@ -65,9 +87,10 @@ class RedisStorage implements CacheStorageInterface
|
|||
}
|
||||
|
||||
/**
|
||||
* Updates the file count in Redis
|
||||
* Atualiza a contagem de arquivos no Redis
|
||||
*
|
||||
* @param int $count Número de arquivos
|
||||
* @param int $count Number of files / Número de arquivos
|
||||
*/
|
||||
public function updateCacheFileCount(int $count): void
|
||||
{
|
||||
|
@ -77,7 +100,11 @@ class RedisStorage implements CacheStorageInterface
|
|||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
* Checks if cache exists for a given ID
|
||||
* Verifica se existe cache para um determinado ID
|
||||
*
|
||||
* @param string $id Cache ID / ID do cache
|
||||
* @return bool True if cache exists, false otherwise / True se o cache existir, false caso contrário
|
||||
*/
|
||||
public function exists(string $id): bool
|
||||
{
|
||||
|
@ -85,7 +112,11 @@ class RedisStorage implements CacheStorageInterface
|
|||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
* Retrieves cached content
|
||||
* Recupera o conteúdo em cache
|
||||
*
|
||||
* @param string $id Cache ID / ID do cache
|
||||
* @return string|null Cached content or null if not found / Conteúdo em cache ou null se não encontrado
|
||||
*/
|
||||
public function get(string $id): ?string
|
||||
{
|
||||
|
@ -93,25 +124,36 @@ class RedisStorage implements CacheStorageInterface
|
|||
return null;
|
||||
}
|
||||
|
||||
/** @var string|false $content */
|
||||
$content = $this->redis->get($id);
|
||||
return $content === false ? null : $content;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
* Stores content in cache
|
||||
* Armazena conteúdo em cache
|
||||
*
|
||||
* @param string $id Cache ID / ID do cache
|
||||
* @param string $content Content to be stored / Conteúdo a ser armazenado
|
||||
* @return bool True if successful, false otherwise / True se bem sucedido, false caso contrário
|
||||
*/
|
||||
public function set(string $id, string $content): bool
|
||||
{
|
||||
// If Redis is not available, return false
|
||||
// Se Redis não estiver disponível, retorna false
|
||||
if ($this->redis === null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// When saving a new file, update the count
|
||||
// Ao salvar um novo arquivo, atualiza a contagem
|
||||
/** @var bool $result */
|
||||
$result = $this->redis->set($id, $content);
|
||||
|
||||
if ($result) {
|
||||
// Increment file count in Redis
|
||||
// Incrementa a contagem de arquivos no Redis
|
||||
/** @var string|false $currentCount */
|
||||
$currentCount = $this->redis->get('cache_file_count') ?: 0;
|
||||
$this->redis->set('cache_file_count', $currentCount + 1);
|
||||
}
|
||||
|
|
|
@ -5,32 +5,44 @@ namespace Inc\Cache;
|
|||
use Aws\S3\S3Client;
|
||||
use Aws\Exception\AwsException;
|
||||
|
||||
/**
|
||||
* AWS S3-based cache storage implementation
|
||||
* Implementação de armazenamento de cache baseado em AWS S3
|
||||
*
|
||||
* This class provides cache storage functionality using Amazon S3 or compatible services
|
||||
* Esta classe fornece funcionalidade de armazenamento de cache usando Amazon S3 ou serviços compatíveis
|
||||
*/
|
||||
class S3Storage implements CacheStorageInterface
|
||||
{
|
||||
/**
|
||||
* @var S3Client AWS S3 Client
|
||||
* @var S3Client Cliente AWS S3
|
||||
*/
|
||||
private $s3Client;
|
||||
|
||||
/**
|
||||
* @var string S3 bucket name
|
||||
* @var string Nome do bucket S3
|
||||
*/
|
||||
private $bucket;
|
||||
|
||||
/**
|
||||
* @var string Prefix for objects in the bucket (optional)
|
||||
* @var string Prefixo para os objetos no bucket (opcional)
|
||||
*/
|
||||
private $prefix;
|
||||
|
||||
/**
|
||||
* @var string ACL for S3 objects
|
||||
* @var string ACL para os objetos no S3
|
||||
*/
|
||||
private $acl;
|
||||
|
||||
/**
|
||||
* Class constructor
|
||||
* Construtor da classe
|
||||
*
|
||||
* @param array $config Configuração do AWS S3
|
||||
* @param array $config AWS S3 configuration / Configuração do AWS S3
|
||||
*/
|
||||
public function __construct(array $config)
|
||||
{
|
||||
|
@ -43,10 +55,12 @@ class S3Storage implements CacheStorageInterface
|
|||
]
|
||||
];
|
||||
|
||||
// Add custom endpoint if provided
|
||||
// Adiciona endpoint personalizado se fornecido
|
||||
if (!empty($config['endpoint'])) {
|
||||
$clientConfig['endpoint'] = $config['endpoint'];
|
||||
// Use path-style endpoints quando um endpoint personalizado é fornecido
|
||||
// Use path-style endpoints when a custom endpoint is provided
|
||||
// Use endpoints estilo path quando um endpoint personalizado é fornecido
|
||||
$clientConfig['use_path_style_endpoint'] = true;
|
||||
}
|
||||
|
||||
|
@ -58,10 +72,11 @@ class S3Storage implements CacheStorageInterface
|
|||
}
|
||||
|
||||
/**
|
||||
* Generates the complete object key in S3
|
||||
* Gera a chave completa do objeto no S3
|
||||
*
|
||||
* @param string $id ID do cache
|
||||
* @return string
|
||||
* @param string $id Cache ID / ID do cache
|
||||
* @return string Complete S3 object key / Chave completa do objeto no S3
|
||||
*/
|
||||
private function getObjectKey(string $id): string
|
||||
{
|
||||
|
@ -69,7 +84,11 @@ class S3Storage implements CacheStorageInterface
|
|||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
* Checks if cache exists for a given ID
|
||||
* Verifica se existe cache para um determinado ID
|
||||
*
|
||||
* @param string $id Cache ID / ID do cache
|
||||
* @return bool True if cache exists, false otherwise / True se o cache existir, false caso contrário
|
||||
*/
|
||||
public function exists(string $id): bool
|
||||
{
|
||||
|
@ -79,13 +98,17 @@ class S3Storage implements CacheStorageInterface
|
|||
$this->getObjectKey($id)
|
||||
);
|
||||
} catch (AwsException $e) {
|
||||
// Log error if needed
|
||||
// Log error if needed / Registra erro se necessário
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
* Retrieves cached content
|
||||
* Recupera o conteúdo em cache
|
||||
*
|
||||
* @param string $id Cache ID / ID do cache
|
||||
* @return string|null Cached content or null if not found / Conteúdo em cache ou null se não encontrado
|
||||
*/
|
||||
public function get(string $id): ?string
|
||||
{
|
||||
|
@ -112,7 +135,12 @@ class S3Storage implements CacheStorageInterface
|
|||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
* Stores content in cache
|
||||
* Armazena conteúdo em cache
|
||||
*
|
||||
* @param string $id Cache ID / ID do cache
|
||||
* @param string $content Content to be stored / Conteúdo a ser armazenado
|
||||
* @return bool True if successful, false otherwise / True se bem sucedido, false caso contrário
|
||||
*/
|
||||
public function set(string $id, string $content): bool
|
||||
{
|
||||
|
@ -128,12 +156,12 @@ class S3Storage implements CacheStorageInterface
|
|||
'Body' => $compressedContent,
|
||||
'ACL' => $this->acl,
|
||||
'ContentEncoding' => 'gzip',
|
||||
'CacheControl' => 'max-age=31536000' // 1 year
|
||||
'CacheControl' => 'max-age=31536000' // 1 year / 1 ano
|
||||
]);
|
||||
|
||||
return true;
|
||||
} catch (AwsException $e) {
|
||||
// Log error if needed
|
||||
// Log error if needed / Registra erro se necessário
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,9 +1,28 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* Language Management Class
|
||||
* Classe de Gerenciamento de Idiomas
|
||||
*
|
||||
* This class handles the loading and retrieval of language-specific strings
|
||||
* Esta classe lida com o carregamento e recuperação de strings específicas do idioma
|
||||
*
|
||||
* Features / Funcionalidades:
|
||||
* - Language initialization / Inicialização de idioma
|
||||
* - Translation retrieval / Recuperação de traduções
|
||||
* - Message handling / Manipulação de mensagens
|
||||
* - Fallback language support / Suporte a idioma de fallback
|
||||
*/
|
||||
class Language {
|
||||
private static $translations = [];
|
||||
private static $currentLanguage = 'pt-br';
|
||||
|
||||
/**
|
||||
* Initialize the language system
|
||||
* Inicializa o sistema de idiomas
|
||||
*
|
||||
* @param string $language Language code (e.g., 'en', 'pt-br') / Código do idioma (ex: 'en', 'pt-br')
|
||||
*/
|
||||
public static function init($language = 'pt-br') {
|
||||
self::$currentLanguage = strtolower($language);
|
||||
$langFile = __DIR__ . '/../languages/' . self::$currentLanguage . '.php';
|
||||
|
@ -12,15 +31,31 @@ class Language {
|
|||
self::$translations = require $langFile;
|
||||
} else {
|
||||
// Fallback to pt-br if language file doesn't exist
|
||||
// Volta para pt-br se o arquivo de idioma não existir
|
||||
self::$currentLanguage = 'pt-br';
|
||||
self::$translations = require __DIR__ . '/../languages/pt-br.php';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a translation by key
|
||||
* Obtém uma tradução por chave
|
||||
*
|
||||
* @param string $key Translation key / Chave da tradução
|
||||
* @param string $default Default value if key not found / Valor padrão se a chave não for encontrada
|
||||
* @return string Translation text / Texto traduzido
|
||||
*/
|
||||
public static function get($key, $default = '') {
|
||||
return self::$translations[$key] ?? $default;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a message by key
|
||||
* Obtém uma mensagem por chave
|
||||
*
|
||||
* @param string $key Message key / Chave da mensagem
|
||||
* @return array Message data (message and type) / Dados da mensagem (mensagem e tipo)
|
||||
*/
|
||||
public static function getMessage($key) {
|
||||
return self::$translations['messages'][$key] ?? [
|
||||
'message' => 'Unknown message',
|
||||
|
@ -28,6 +63,12 @@ class Language {
|
|||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get current language code
|
||||
* Obtém o código do idioma atual
|
||||
*
|
||||
* @return string Current language code / Código do idioma atual
|
||||
*/
|
||||
public static function getCurrentLanguage() {
|
||||
return self::$currentLanguage;
|
||||
}
|
||||
|
|
|
@ -5,18 +5,46 @@ namespace Inc;
|
|||
use Exception;
|
||||
use \Hawk\Catcher;
|
||||
|
||||
/**
|
||||
* Error logging and monitoring class
|
||||
* Classe de monitoramento e registro de erros
|
||||
*
|
||||
* This class implements error logging functionality using Hawk.so
|
||||
* for monitoring and tracking application errors.
|
||||
*
|
||||
* Esta classe implementa funcionalidades de registro de erros usando Hawk.so
|
||||
* para monitoramento e rastreamento de erros da aplicação.
|
||||
*/
|
||||
class Logger
|
||||
{
|
||||
/**
|
||||
* @var Logger|null Singleton instance
|
||||
* @var Logger|null Instância singleton
|
||||
*/
|
||||
private static $instance = null;
|
||||
|
||||
/**
|
||||
* Private constructor to prevent direct instantiation
|
||||
* Construtor privado para prevenir instanciação direta
|
||||
*
|
||||
* Initializes Hawk monitoring
|
||||
* Inicializa o monitoramento Hawk
|
||||
*/
|
||||
private function __construct()
|
||||
{
|
||||
// Initialize Hawk
|
||||
// Inicializa o Hawk
|
||||
Catcher::init([
|
||||
'integrationToken' => HAWK_TOKEN,
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets singleton instance
|
||||
* Obtém instância singleton
|
||||
*
|
||||
* @return Logger Instance of Logger / Instância do Logger
|
||||
*/
|
||||
public static function getInstance(): Logger
|
||||
{
|
||||
if (self::$instance === null) {
|
||||
|
@ -26,14 +54,16 @@ class Logger
|
|||
}
|
||||
|
||||
/**
|
||||
* Logs an error with context
|
||||
* Registra um erro com contexto
|
||||
*
|
||||
* @param string $message Mensagem de erro
|
||||
* @param array $context Dados adicionais de contexto
|
||||
* @param string $type Tipo/categoria do erro
|
||||
* @param string $message Error message / Mensagem de erro
|
||||
* @param array $context Additional context data / Dados adicionais de contexto
|
||||
* @param string $type Error type/category / Tipo/categoria do erro
|
||||
*/
|
||||
public function error(string $message, array $context = [], string $type = 'WARNING'): void
|
||||
{
|
||||
// Log to Hawk
|
||||
// Registra no Hawk
|
||||
try {
|
||||
Catcher::get()->sendException(new Exception($message), [
|
||||
|
@ -41,21 +71,24 @@ class Logger
|
|||
'context' => $context
|
||||
]);
|
||||
} catch (Exception $e) {
|
||||
// If Hawk fails, we already have file logging as backup
|
||||
// Se o Hawk falhar, já temos o log em arquivo como backup
|
||||
error_log("Falha ao enviar erro para o Hawk: " . $e->getMessage());
|
||||
error_log("Failed to send error to Hawk / Falha ao enviar erro para o Hawk: " . $e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Logs a URL-specific error
|
||||
* Registra um erro específico de URL
|
||||
*
|
||||
* @param string $url A URL que gerou o erro
|
||||
* @param string $error_group Grupo/categoria do erro
|
||||
* @param string $message_error Detalhes adicionais do erro
|
||||
* @param string $type Tipo/categoria do erro
|
||||
* @param string $url The URL that generated the error / A URL que gerou o erro
|
||||
* @param string $error_group Error group/category / Grupo/categoria do erro
|
||||
* @param string $message_error Additional error details / Detalhes adicionais do erro
|
||||
* @param string $type Error type/category / Tipo/categoria do erro
|
||||
*/
|
||||
public function log(string $url, string $error_group, string $message_error = '', string $type = 'WARNING'): void
|
||||
{
|
||||
// If no Hawk token is configured, don't generate log
|
||||
// Se não houver token do Hawk configurado, não gera log
|
||||
if (empty(HAWK_TOKEN)) {
|
||||
return;
|
||||
|
|
|
@ -1,8 +1,14 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* Class responsible for content manipulation rules management
|
||||
* Classe responsável pelo gerenciamento de regras de manipulação de conteúdo
|
||||
*
|
||||
* This class implements a rules system for different web domains,
|
||||
* allowing system behavior customization for each site.
|
||||
* Includes functionalities for paywall removal, specific elements,
|
||||
* cookie manipulation and custom code execution.
|
||||
*
|
||||
* Esta classe implementa um sistema de regras para diferentes domínios web,
|
||||
* permitindo a personalização do comportamento do sistema para cada site.
|
||||
* Inclui funcionalidades para remoção de paywalls, elementos específicos,
|
||||
|
@ -11,17 +17,24 @@
|
|||
class Rules
|
||||
{
|
||||
/**
|
||||
* Associative array containing specific rules for each domain
|
||||
* Array associativo contendo regras específicas para cada domínio
|
||||
*
|
||||
* Possible configurations for each domain:
|
||||
* Configurações possíveis para cada domínio:
|
||||
* @var array
|
||||
*/
|
||||
private $domainRules = DOMAIN_RULES;
|
||||
|
||||
// Regras globais expandidas
|
||||
/**
|
||||
* Expanded global rules
|
||||
* Regras globais expandidas
|
||||
* @var array
|
||||
*/
|
||||
private $globalRules = GLOBAL_RULES;
|
||||
|
||||
/**
|
||||
* List of supported rule types
|
||||
* Lista de tipos de regras suportados
|
||||
* @var array
|
||||
*/
|
||||
|
@ -41,10 +54,11 @@ class Rules
|
|||
];
|
||||
|
||||
/**
|
||||
* Gets the base domain by removing www prefix
|
||||
* Obtém o domínio base removendo o prefixo www
|
||||
*
|
||||
* @param string $domain Domínio completo
|
||||
* @return string Domínio base sem www
|
||||
* @param string $domain Full domain / Domínio completo
|
||||
* @return string Base domain without www / Domínio base sem www
|
||||
*/
|
||||
private function getBaseDomain($domain)
|
||||
{
|
||||
|
@ -52,10 +66,11 @@ class Rules
|
|||
}
|
||||
|
||||
/**
|
||||
* Splits a domain into its constituent parts
|
||||
* Divide um domínio em suas partes constituintes
|
||||
*
|
||||
* @param string $domain Domínio a ser dividido
|
||||
* @return array Array com todas as combinações possíveis do domínio
|
||||
* @param string $domain Domain to be split / Domínio a ser dividido
|
||||
* @return array Array with all possible domain combinations / Array com todas as combinações possíveis do domínio
|
||||
*/
|
||||
private function getDomainParts($domain)
|
||||
{
|
||||
|
@ -75,10 +90,11 @@ class Rules
|
|||
}
|
||||
|
||||
/**
|
||||
* Gets specific rules for a domain
|
||||
* Obtém as regras específicas para um domínio
|
||||
*
|
||||
* @param string $domain Domínio para buscar regras
|
||||
* @return array|null Array com regras mescladas ou null se não encontrar
|
||||
* @param string $domain Domain to search rules for / Domínio para buscar regras
|
||||
* @return array|null Array with merged rules or null if not found / Array com regras mescladas ou null se não encontrar
|
||||
*/
|
||||
public function getDomainRules($domain)
|
||||
{
|
||||
|
@ -98,25 +114,29 @@ class Rules
|
|||
}
|
||||
}
|
||||
|
||||
// If no specific rules found, return only global rules
|
||||
// Se não encontrou regras específicas, retorna apenas as regras globais
|
||||
return $this->getGlobalRules();
|
||||
}
|
||||
|
||||
/**
|
||||
* Merges domain-specific rules with global rules
|
||||
* Mescla regras específicas do domínio com regras globais
|
||||
*
|
||||
* @param array $rules Regras específicas do domínio
|
||||
* @return array Regras mescladas
|
||||
* @param array $rules Domain-specific rules / Regras específicas do domínio
|
||||
* @return array Merged rules / Regras mescladas
|
||||
*/
|
||||
private function mergeWithGlobalRules($rules)
|
||||
{
|
||||
$globalRules = $this->getGlobalRules();
|
||||
$mergedRules = [];
|
||||
|
||||
// Process global rules exclusions
|
||||
// Processa as exclusões de regras globais
|
||||
$excludeGlobalRules = isset($rules['excludeGlobalRules']) ? $rules['excludeGlobalRules'] : [];
|
||||
unset($rules['excludeGlobalRules']); // Remove do array de regras para não ser processado como regra normal
|
||||
unset($rules['excludeGlobalRules']); // Remove from rules array to avoid processing as normal rule / Remove do array de regras para não ser processado como regra normal
|
||||
|
||||
// First, add all global rules except excluded ones
|
||||
// Primeiro, adiciona todas as regras globais, exceto as excluídas
|
||||
foreach ($globalRules as $ruleType => $globalTypeRules) {
|
||||
if (!in_array($ruleType, $this->supportedRuleTypes)) {
|
||||
|
@ -124,10 +144,12 @@ class Rules
|
|||
}
|
||||
|
||||
if (isset($excludeGlobalRules[$ruleType])) {
|
||||
// If rule type is an associative array (like cookies or headers)
|
||||
// Se o tipo de regra é um array associativo (como cookies ou headers)
|
||||
if (is_array($globalTypeRules) && array_keys($globalTypeRules) !== range(0, count($globalTypeRules) - 1)) {
|
||||
$mergedRules[$ruleType] = array_diff_key($globalTypeRules, array_flip($excludeGlobalRules[$ruleType]));
|
||||
} else {
|
||||
// For simple arrays (like classElementRemove)
|
||||
// Para arrays simples (como classElementRemove)
|
||||
$mergedRules[$ruleType] = array_diff($globalTypeRules, $excludeGlobalRules[$ruleType]);
|
||||
}
|
||||
|
@ -136,6 +158,7 @@ class Rules
|
|||
}
|
||||
}
|
||||
|
||||
// Then, merge with domain-specific rules
|
||||
// Depois, mescla com as regras específicas do domínio
|
||||
foreach ($rules as $ruleType => $domainTypeRules) {
|
||||
if (!in_array($ruleType, $this->supportedRuleTypes)) {
|
||||
|
@ -147,11 +170,14 @@ class Rules
|
|||
continue;
|
||||
}
|
||||
|
||||
// If rule type already exists, merge appropriately
|
||||
// Se o tipo de regra já existe, mescla apropriadamente
|
||||
if (in_array($ruleType, ['cookies', 'headers'])) {
|
||||
// For cookies and headers, preserve keys
|
||||
// Para cookies e headers, preserva as chaves
|
||||
$mergedRules[$ruleType] = array_merge($mergedRules[$ruleType], $domainTypeRules);
|
||||
} else {
|
||||
// For other types, merge as simple arrays
|
||||
// Para outros tipos, mescla como arrays simples
|
||||
$mergedRules[$ruleType] = array_values(array_unique(array_merge(
|
||||
$mergedRules[$ruleType],
|
||||
|
@ -164,9 +190,10 @@ class Rules
|
|||
}
|
||||
|
||||
/**
|
||||
* Returns all global rules
|
||||
* Retorna todas as regras globais
|
||||
*
|
||||
* @return array Array com todas as regras globais
|
||||
* @return array Array with all global rules / Array com todas as regras globais
|
||||
*/
|
||||
public function getGlobalRules()
|
||||
{
|
||||
|
|
|
@ -1,16 +1,19 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* Class responsible for URL analysis and processing
|
||||
* Classe responsável pela análise e processamento de URLs
|
||||
*
|
||||
* This class implements functionalities for:
|
||||
* Esta classe implementa funcionalidades para:
|
||||
* - Análise e limpeza de URLs
|
||||
* - Cache de conteúdo
|
||||
* - Resolução DNS
|
||||
* - Requisições HTTP com múltiplas tentativas
|
||||
* - Processamento de conteúdo baseado em regras específicas por domínio
|
||||
* - Suporte a Wayback Machine como fallback
|
||||
* - Suporte a extração via Selenium quando habilitado por domínio
|
||||
*
|
||||
* - URL analysis and cleaning / Análise e limpeza de URLs
|
||||
* - Content caching / Cache de conteúdo
|
||||
* - DNS resolution / Resolução DNS
|
||||
* - HTTP requests with multiple attempts / Requisições HTTP com múltiplas tentativas
|
||||
* - Content processing based on domain-specific rules / Processamento de conteúdo baseado em regras específicas por domínio
|
||||
* - Wayback Machine support as fallback / Suporte a Wayback Machine como fallback
|
||||
* - Selenium extraction support when enabled by domain / Suporte a extração via Selenium quando habilitado por domínio
|
||||
*/
|
||||
|
||||
require_once 'Rules.php';
|
||||
|
@ -28,32 +31,40 @@ use Inc\Logger;
|
|||
class URLAnalyzer
|
||||
{
|
||||
/**
|
||||
* @var array List of available User Agents for requests
|
||||
* @var array Lista de User Agents disponíveis para requisições
|
||||
*/
|
||||
private $userAgents;
|
||||
|
||||
/**
|
||||
* @var array List of DNS servers for resolution
|
||||
* @var array Lista de servidores DNS para resolução
|
||||
*/
|
||||
private $dnsServers;
|
||||
|
||||
/**
|
||||
* @var Rules Instance of rules class
|
||||
* @var Rules Instância da classe de regras
|
||||
*/
|
||||
private $rules;
|
||||
|
||||
/**
|
||||
* @var Cache Instance of cache class
|
||||
* @var Cache Instância da classe de cache
|
||||
*/
|
||||
private $cache;
|
||||
|
||||
/**
|
||||
* @var array List of rules activated during processing
|
||||
* @var array Lista de regras ativadas durante o processamento
|
||||
*/
|
||||
private $activatedRules = [];
|
||||
|
||||
/**
|
||||
* Class constructor
|
||||
* Construtor da classe
|
||||
*
|
||||
* Initializes required dependencies
|
||||
* Inicializa as dependências necessárias
|
||||
*/
|
||||
public function __construct()
|
||||
|
@ -65,10 +76,11 @@ class URLAnalyzer
|
|||
}
|
||||
|
||||
/**
|
||||
* Check if a URL has redirects and return the final URL
|
||||
* Verifica se uma URL tem redirecionamentos e retorna a URL final
|
||||
*
|
||||
* @param string $url URL para verificar redirecionamentos
|
||||
* @return array Array com a URL final e se houve redirecionamento
|
||||
* @param string $url URL to check redirects / URL para verificar redirecionamentos
|
||||
* @return array Array with final URL and if there was a redirect / Array com a URL final e se houve redirecionamento
|
||||
*/
|
||||
public function checkRedirects($url)
|
||||
{
|
||||
|
@ -96,37 +108,39 @@ class URLAnalyzer
|
|||
}
|
||||
|
||||
/**
|
||||
* Main method for URL analysis
|
||||
* Método principal para análise de URLs
|
||||
*
|
||||
* @param string $url URL a ser analisada
|
||||
* @return string Conteúdo processado da URL
|
||||
* @throws Exception Em caso de erros durante o processamento
|
||||
* @param string $url URL to be analyzed / URL a ser analisada
|
||||
* @return string Processed content / Conteúdo processado
|
||||
* @throws Exception In case of processing errors / Em caso de erros durante o processamento
|
||||
*/
|
||||
public function analyze($url)
|
||||
{
|
||||
// Reset activated rules for new analysis
|
||||
// Reset das regras ativadas para nova análise
|
||||
$this->activatedRules = [];
|
||||
|
||||
// 1. Limpa a URL
|
||||
// 1. Clean URL / Limpa a URL
|
||||
$cleanUrl = $this->cleanUrl($url);
|
||||
if (!$cleanUrl) {
|
||||
throw new Exception("URL inválida");
|
||||
throw new Exception(Language::getMessage('INVALID_URL')['message']);
|
||||
}
|
||||
|
||||
// 2. Verifica cache
|
||||
// 2. Check cache / Verifica cache
|
||||
if ($this->cache->exists($cleanUrl)) {
|
||||
return $this->cache->get($cleanUrl);
|
||||
}
|
||||
|
||||
// 3. Verifica domínios bloqueados
|
||||
// 3. Check blocked domains / Verifica domínios bloqueados
|
||||
$host = parse_url($cleanUrl, PHP_URL_HOST);
|
||||
$host = preg_replace('/^www\./', '', $host);
|
||||
|
||||
if (in_array($host, BLOCKED_DOMAINS)) {
|
||||
throw new Exception('Este domínio está bloqueado para extração.');
|
||||
throw new Exception(Language::getMessage('BLOCKED_DOMAIN')['message']);
|
||||
}
|
||||
|
||||
// 4. Verifica se deve usar Selenium
|
||||
// 4. Check if should use Selenium / Verifica se deve usar Selenium
|
||||
$domainRules = $this->getDomainRules($host);
|
||||
if (isset($domainRules['useSelenium']) && $domainRules['useSelenium'] === true) {
|
||||
try {
|
||||
|
@ -137,13 +151,12 @@ class URLAnalyzer
|
|||
return $processedContent;
|
||||
}
|
||||
} catch (Exception $e) {
|
||||
$error = 'SELENIUM_ERROR';
|
||||
Logger::getInstance()->log($cleanUrl, 'SELENIUM_ERROR', $e->getMessage());
|
||||
throw new Exception($error);
|
||||
throw new Exception(Language::getMessage('CONTENT_ERROR')['message']);
|
||||
}
|
||||
}
|
||||
|
||||
// 5. Tenta buscar conteúdo diretamente
|
||||
// 5. Try to fetch content directly / Tenta buscar conteúdo diretamente
|
||||
try {
|
||||
$content = $this->fetchContent($cleanUrl);
|
||||
if (!empty($content)) {
|
||||
|
@ -155,7 +168,7 @@ class URLAnalyzer
|
|||
error_log("DIRECT_FETCH_ERROR: " . $e->getMessage());
|
||||
}
|
||||
|
||||
// 6. Tenta buscar do Wayback Machine como fallback
|
||||
// 6. Try to fetch from Wayback Machine as fallback / Tenta buscar do Wayback Machine como fallback
|
||||
try {
|
||||
$content = $this->fetchFromWaybackMachine($cleanUrl);
|
||||
if (!empty($content)) {
|
||||
|
@ -167,7 +180,7 @@ class URLAnalyzer
|
|||
error_log("WAYBACK_FETCH_ERROR: " . $e->getMessage());
|
||||
}
|
||||
|
||||
// 7. Tenta buscar com Selenium como fallback
|
||||
// 7. Try to fetch with Selenium as fallback / Tenta buscar com Selenium como fallback
|
||||
try {
|
||||
$content = $this->fetchFromSelenium($cleanUrl, 'firefox');
|
||||
if (!empty($content)) {
|
||||
|
@ -180,16 +193,17 @@ class URLAnalyzer
|
|||
}
|
||||
|
||||
Logger::getInstance()->log($cleanUrl, 'GENERAL_FETCH_ERROR');
|
||||
throw new Exception("Não foi possível obter o conteúdo da URL");
|
||||
throw new Exception(Language::getMessage('CONTENT_ERROR')['message']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Try to get content using Selenium
|
||||
* Tenta obter o conteúdo da URL usando Selenium
|
||||
*
|
||||
* @param string $url URL para buscar
|
||||
* @param array $domainRules Regras específicas do domínio
|
||||
* @return string|null Conteúdo HTML da página
|
||||
* @throws Exception Em caso de erro na requisição
|
||||
* @param string $url URL to fetch / URL para buscar
|
||||
* @param string $browser Browser to use (chrome/firefox) / Navegador a ser usado (chrome/firefox)
|
||||
* @return string|null HTML content of the page / Conteúdo HTML da página
|
||||
* @throws Exception In case of request error / Em caso de erro na requisição
|
||||
*/
|
||||
private function fetchFromSelenium($url, $browser)
|
||||
{
|
||||
|
@ -210,12 +224,12 @@ class URLAnalyzer
|
|||
$capabilities->setCapability(ChromeOptions::CAPABILITY, $options);
|
||||
} else {
|
||||
$profile = new FirefoxProfile();
|
||||
$profile->setPreference("permissions.default.image", 2); // Não carrega imagens
|
||||
$profile->setPreference("javascript.enabled", true); // Mantem habilitado javascripts
|
||||
$profile->setPreference("network.http.referer.defaultPolicy", 0); // Sempre envia referer
|
||||
$profile->setPreference("network.http.referer.defaultReferer", "https://www.google.com.br"); // Define referer padrão
|
||||
$profile->setPreference("network.http.referer.spoofSource", true); // Permite spoofing do referer
|
||||
$profile->setPreference("network.http.referer.trimmingPolicy", 0); // Não corta o referer
|
||||
$profile->setPreference("permissions.default.image", 2); // Don't load images / Não carrega imagens
|
||||
$profile->setPreference("javascript.enabled", true); // Keep JavaScript enabled / Mantém JavaScript habilitado
|
||||
$profile->setPreference("network.http.referer.defaultPolicy", 0); // Always send referer / Sempre envia referer
|
||||
$profile->setPreference("network.http.referer.defaultReferer", "https://www.google.com.br"); // Set default referer / Define referer padrão
|
||||
$profile->setPreference("network.http.referer.spoofSource", true); // Allow referer spoofing / Permite spoofing do referer
|
||||
$profile->setPreference("network.http.referer.trimmingPolicy", 0); // Don't trim referer / Não corta o referer
|
||||
|
||||
$options = new FirefoxOptions();
|
||||
$options->setProfile($profile);
|
||||
|
@ -232,12 +246,11 @@ class URLAnalyzer
|
|||
$driver->get($url);
|
||||
|
||||
$htmlSource = $driver->executeScript("return document.documentElement.outerHTML;");
|
||||
//$htmlSource = $driver->getPageSource();
|
||||
|
||||
$driver->quit();
|
||||
|
||||
if (empty($htmlSource)) {
|
||||
throw new Exception("Selenium returned empty content");
|
||||
throw new Exception("Selenium returned empty content / Selenium retornou conteúdo vazio");
|
||||
}
|
||||
|
||||
return $htmlSource;
|
||||
|
@ -250,11 +263,12 @@ class URLAnalyzer
|
|||
}
|
||||
|
||||
/**
|
||||
* Try to get content from Internet Archive's Wayback Machine
|
||||
* Tenta obter o conteúdo da URL do Internet Archive's Wayback Machine
|
||||
*
|
||||
* @param string $url URL original
|
||||
* @return string|null Conteúdo do arquivo
|
||||
* @throws Exception Em caso de erro na requisição
|
||||
* @param string $url Original URL / URL original
|
||||
* @return string|null Archive content / Conteúdo do arquivo
|
||||
* @throws Exception In case of request error / Em caso de erro na requisição
|
||||
*/
|
||||
private function fetchFromWaybackMachine($url)
|
||||
{
|
||||
|
@ -270,12 +284,12 @@ class URLAnalyzer
|
|||
$curl->get($availabilityUrl);
|
||||
|
||||
if ($curl->error || $curl->httpStatusCode !== 200) {
|
||||
throw new Exception("Erro ao verificar disponibilidade no Wayback Machine");
|
||||
throw new Exception(Language::getMessage('HTTP_ERROR')['message']);
|
||||
}
|
||||
|
||||
$data = $curl->response;
|
||||
if (!isset($data->archived_snapshots->closest->url)) {
|
||||
throw new Exception("Nenhum snapshot encontrado no Wayback Machine");
|
||||
throw new Exception(Language::getMessage('CONTENT_ERROR')['message']);
|
||||
}
|
||||
|
||||
$archiveUrl = $data->archived_snapshots->closest->url;
|
||||
|
@ -288,11 +302,12 @@ class URLAnalyzer
|
|||
$curl->get($archiveUrl);
|
||||
|
||||
if ($curl->error || $curl->httpStatusCode !== 200 || empty($curl->response)) {
|
||||
throw new Exception("Erro ao obter conteúdo do Wayback Machine");
|
||||
throw new Exception(Language::getMessage('HTTP_ERROR')['message']);
|
||||
}
|
||||
|
||||
$content = $curl->response;
|
||||
|
||||
// Remove Wayback Machine toolbar and cache URLs
|
||||
// Remove o toolbar do Wayback Machine e URLs de cache
|
||||
$content = preg_replace('/<!-- BEGIN WAYBACK TOOLBAR INSERT -->.*?<!-- END WAYBACK TOOLBAR INSERT -->/s', '', $content);
|
||||
$content = preg_replace('/https?:\/\/web\.archive\.org\/web\/\d+im_\//', '', $content);
|
||||
|
@ -301,11 +316,12 @@ class URLAnalyzer
|
|||
}
|
||||
|
||||
/**
|
||||
* Perform HTTP request using Curl Class
|
||||
* Realiza requisição HTTP usando Curl Class
|
||||
*
|
||||
* @param string $url URL para requisição
|
||||
* @return string Conteúdo da página
|
||||
* @throws Exception Em caso de erro na requisição
|
||||
* @param string $url URL for request / URL para requisição
|
||||
* @return string Page content / Conteúdo da página
|
||||
* @throws Exception In case of request error / Em caso de erro na requisição
|
||||
*/
|
||||
private function fetchContent($url)
|
||||
{
|
||||
|
@ -320,13 +336,13 @@ class URLAnalyzer
|
|||
$curl->setOpt(CURLOPT_SSL_VERIFYPEER, false);
|
||||
$curl->setOpt(CURLOPT_DNS_SERVERS, implode(',', $this->dnsServers));
|
||||
|
||||
// Define User Agent
|
||||
// Set User Agent / Define User Agent
|
||||
$userAgent = isset($domainRules['userAgent'])
|
||||
? $domainRules['userAgent']
|
||||
: $this->userAgents[array_rand($this->userAgents)];
|
||||
$curl->setUserAgent($userAgent);
|
||||
|
||||
// Headers padrão
|
||||
// Default headers / Headers padrão
|
||||
$headers = [
|
||||
'Host' => $host,
|
||||
'Accept' => 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8',
|
||||
|
@ -335,13 +351,13 @@ class URLAnalyzer
|
|||
'Pragma' => 'no-cache'
|
||||
];
|
||||
|
||||
// Adiciona headers específicos do domínio
|
||||
// Add domain-specific headers / Adiciona headers específicos do domínio
|
||||
if (isset($domainRules['headers'])) {
|
||||
$headers = array_merge($headers, $domainRules['headers']);
|
||||
}
|
||||
$curl->setHeaders($headers);
|
||||
|
||||
// Adiciona cookies específicos do domínio
|
||||
// Add domain-specific cookies / Adiciona cookies específicos do domínio
|
||||
if (isset($domainRules['cookies'])) {
|
||||
$cookies = [];
|
||||
foreach ($domainRules['cookies'] as $name => $value) {
|
||||
|
@ -354,7 +370,7 @@ class URLAnalyzer
|
|||
}
|
||||
}
|
||||
|
||||
// Adiciona referer se especificado
|
||||
// Add referer if specified / Adiciona referer se especificado
|
||||
if (isset($domainRules['referer'])) {
|
||||
$curl->setHeader('Referer', $domainRules['referer']);
|
||||
}
|
||||
|
@ -362,43 +378,44 @@ class URLAnalyzer
|
|||
$curl->get($url);
|
||||
|
||||
if ($curl->error || $curl->httpStatusCode !== 200) {
|
||||
throw new Exception("Erro HTTP " . $curl->httpStatusCode . ": " . $curl->errorMessage);
|
||||
throw new Exception(Language::getMessage('HTTP_ERROR')['message']);
|
||||
}
|
||||
|
||||
if (empty($curl->response)) {
|
||||
throw new Exception("Resposta vazia do servidor");
|
||||
throw new Exception(Language::getMessage('CONTENT_ERROR')['message']);
|
||||
}
|
||||
|
||||
return $curl->response;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clean and normalize a URL
|
||||
* Limpa e normaliza uma URL
|
||||
*
|
||||
* @param string $url URL para limpar
|
||||
* @return string|false URL limpa e normalizada ou false se inválida
|
||||
* @param string $url URL to clean / URL para limpar
|
||||
* @return string|false Cleaned and normalized URL or false if invalid / URL limpa e normalizada ou false se inválida
|
||||
*/
|
||||
private function cleanUrl($url)
|
||||
{
|
||||
$url = trim($url);
|
||||
|
||||
// Verifica se a URL é válida
|
||||
// Check if URL is valid / Verifica se a URL é válida
|
||||
if (!filter_var($url, FILTER_VALIDATE_URL)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Detecta e converte URLs AMP
|
||||
// Detect and convert AMP URLs / Detecta e converte URLs AMP
|
||||
if (preg_match('#https://([^.]+)\.cdn\.ampproject\.org/v/s/([^/]+)(.*)#', $url, $matches)) {
|
||||
$url = 'https://' . $matches[2] . $matches[3];
|
||||
}
|
||||
|
||||
// Separa a URL em suas partes componentes
|
||||
// Split URL into component parts / Separa a URL em suas partes componentes
|
||||
$parts = parse_url($url);
|
||||
|
||||
// Reconstrói a URL base
|
||||
// Rebuild base URL / Reconstrói a URL base
|
||||
$cleanedUrl = $parts['scheme'] . '://' . $parts['host'];
|
||||
|
||||
// Adiciona o caminho se existir
|
||||
// Add path if exists / Adiciona o caminho se existir
|
||||
if (isset($parts['path'])) {
|
||||
$cleanedUrl .= $parts['path'];
|
||||
}
|
||||
|
@ -407,10 +424,11 @@ class URLAnalyzer
|
|||
}
|
||||
|
||||
/**
|
||||
* Get specific rules for a domain
|
||||
* Obtém regras específicas para um domínio
|
||||
*
|
||||
* @param string $domain Domínio para buscar regras
|
||||
* @return array|null Regras do domínio ou null se não encontrar
|
||||
* @param string $domain Domain to search rules / Domínio para buscar regras
|
||||
* @return array|null Domain rules or null if not found / Regras do domínio ou null se não encontrar
|
||||
*/
|
||||
private function getDomainRules($domain)
|
||||
{
|
||||
|
@ -418,10 +436,11 @@ class URLAnalyzer
|
|||
}
|
||||
|
||||
/**
|
||||
* Remove specific classes from an element
|
||||
* Remove classes específicas de um elemento
|
||||
*
|
||||
* @param DOMElement $element Elemento DOM
|
||||
* @param array $classesToRemove Classes a serem removidas
|
||||
* @param DOMElement $element DOM Element / Elemento DOM
|
||||
* @param array $classesToRemove Classes to remove / Classes a serem removidas
|
||||
*/
|
||||
private function removeClassNames($element, $classesToRemove)
|
||||
{
|
||||
|
@ -442,11 +461,12 @@ class URLAnalyzer
|
|||
}
|
||||
|
||||
/**
|
||||
* Fix relative URLs in a DOM document
|
||||
* Corrige URLs relativas em um documento DOM
|
||||
*
|
||||
* @param DOMDocument $dom Documento DOM
|
||||
* @param DOMXPath $xpath Objeto XPath
|
||||
* @param string $baseUrl URL base para correção
|
||||
* @param DOMDocument $dom DOM Document / Documento DOM
|
||||
* @param DOMXPath $xpath XPath Object / Objeto XPath
|
||||
* @param string $baseUrl Base URL for correction / URL base para correção
|
||||
*/
|
||||
private function fixRelativeUrls($dom, $xpath, $baseUrl)
|
||||
{
|
||||
|
@ -490,12 +510,13 @@ class URLAnalyzer
|
|||
}
|
||||
|
||||
/**
|
||||
* Process HTML content applying domain rules
|
||||
* Processa o conteúdo HTML aplicando regras do domínio
|
||||
*
|
||||
* @param string $content Conteúdo HTML
|
||||
* @param string $host Nome do host
|
||||
* @param string $url URL completa
|
||||
* @return string Conteúdo processado
|
||||
* @param string $content HTML content / Conteúdo HTML
|
||||
* @param string $host Host name / Nome do host
|
||||
* @param string $url Complete URL / URL completa
|
||||
* @return string Processed content / Conteúdo processado
|
||||
*/
|
||||
private function processContent($content, $host, $url)
|
||||
{
|
||||
|
@ -507,17 +528,17 @@ class URLAnalyzer
|
|||
|
||||
$xpath = new DOMXPath($dom);
|
||||
|
||||
// Processa tags canônicas
|
||||
// Process canonical tags / Processa tags canônicas
|
||||
$canonicalLinks = $xpath->query("//link[@rel='canonical']");
|
||||
if ($canonicalLinks !== false) {
|
||||
// Remove todas as tags canônicas existentes
|
||||
foreach ($canonicalLinks as $link) {
|
||||
if ($link->parentNode) {
|
||||
$link->parentNode->removeChild($link);
|
||||
}
|
||||
}
|
||||
}
|
||||
// Adiciona nova tag canônica com a URL original
|
||||
|
||||
// Add new canonical tag with original URL / Adiciona nova tag canônica com a URL original
|
||||
$head = $xpath->query('//head')->item(0);
|
||||
if ($head) {
|
||||
$newCanonical = $dom->createElement('link');
|
||||
|
@ -526,7 +547,7 @@ class URLAnalyzer
|
|||
$head->appendChild($newCanonical);
|
||||
}
|
||||
|
||||
// Sempre aplica a correção de URLs relativas
|
||||
// Always fix relative URLs / Sempre corrige URLs relativas
|
||||
$this->fixRelativeUrls($dom, $xpath, $url);
|
||||
|
||||
$domainRules = $this->getDomainRules($host);
|
||||
|
@ -586,6 +607,7 @@ class URLAnalyzer
|
|||
|
||||
if (isset($domainRules['scriptTagRemove'])) {
|
||||
foreach ($domainRules['scriptTagRemove'] as $script) {
|
||||
// Search for script tags with src or content containing the script
|
||||
// Busca por tags script com src ou conteúdo contendo o script
|
||||
$scriptElements = $xpath->query("//script[contains(@src, '$script')] | //script[contains(text(), '$script')]");
|
||||
if ($scriptElements !== false && $scriptElements->length > 0) {
|
||||
|
@ -597,6 +619,7 @@ class URLAnalyzer
|
|||
$this->activatedRules[] = "scriptTagRemove: $script";
|
||||
}
|
||||
|
||||
// Search for link tags that are scripts
|
||||
// Busca por tags link que são scripts
|
||||
$linkElements = $xpath->query("//link[@as='script' and contains(@href, '$script') and @type='application/javascript']");
|
||||
if ($linkElements !== false && $linkElements->length > 0) {
|
||||
|
@ -621,7 +644,7 @@ class URLAnalyzer
|
|||
}
|
||||
}
|
||||
|
||||
// Adiciona CTA Marreta
|
||||
// Add Marreta CTA / Adiciona CTA Marreta
|
||||
$body = $xpath->query('//body')->item(0);
|
||||
if ($body) {
|
||||
$marretaDiv = $dom->createElement('div');
|
||||
|
@ -631,14 +654,14 @@ class URLAnalyzer
|
|||
$marretaDiv->appendChild($marretaHtml);
|
||||
$body->appendChild($marretaDiv);
|
||||
|
||||
// Adiciona painel de debug se DEBUG for true
|
||||
// Add debug panel if DEBUG is true / Adiciona painel de debug se DEBUG for true
|
||||
if (DEBUG) {
|
||||
$debugDiv = $dom->createElement('div');
|
||||
$debugDiv->setAttribute('style', 'z-index: 99999; position: fixed; bottom: 10px; right: 10px; background: rgba(0,0,0,0.8); color: #fff; font-size: 13px; line-height: 1.4; padding: 10px; border-radius: 3px; font-family: monospace; max-height: 200px; overflow-y: auto;');
|
||||
|
||||
if( empty($this->activatedRules)) {
|
||||
if (empty($this->activatedRules)) {
|
||||
$ruleElement = $dom->createElement('div');
|
||||
$ruleElement->textContent = 'Nenhuma regra ativada';
|
||||
$ruleElement->textContent = 'No rules activated / Nenhuma regra ativada';
|
||||
$debugDiv->appendChild($ruleElement);
|
||||
} else {
|
||||
foreach ($this->activatedRules as $rule) {
|
||||
|
|
31
app/p.php
31
app/p.php
|
@ -1,55 +1,73 @@
|
|||
<?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
|
||||
*
|
||||
* Exemplo de uso:
|
||||
* Usage example / Exemplo de uso:
|
||||
* /p/https://example.com
|
||||
* /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->checkRedirects($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 (Exception $e) {
|
||||
$errorMessage = $e->getMessage();
|
||||
$errorType = 'GENERIC_ERROR'; // Tipo padrão de erro
|
||||
$errorType = 'GENERIC_ERROR'; // Default error type / Tipo padrão de erro
|
||||
|
||||
// Map error message to specific type
|
||||
// Mapeia a mensagem de erro para um tipo específico
|
||||
if (strpos($errorMessage, 'bloqueado') !== false) {
|
||||
if (strpos($errorMessage, 'bloqueado') !== false || strpos($errorMessage, 'blocked') !== false) {
|
||||
$errorType = 'BLOCKED_DOMAIN';
|
||||
} elseif (strpos($errorMessage, 'DNS') !== false) {
|
||||
$errorType = 'DNS_FAILURE';
|
||||
|
@ -57,21 +75,22 @@ if (strpos($path, $prefix) === 0) {
|
|||
$errorType = 'HTTP_ERROR';
|
||||
} elseif (strpos($errorMessage, 'CURL') !== false) {
|
||||
$errorType = 'CONNECTION_ERROR';
|
||||
} elseif (strpos($errorMessage, 'obter conteúdo') !== false) {
|
||||
} elseif (strpos($errorMessage, 'obter conteúdo') !== false || strpos($errorMessage, 'get content') !== false) {
|
||||
$errorType = 'CONTENT_ERROR';
|
||||
}
|
||||
|
||||
// Redirect to home page with error message
|
||||
// Redireciona para a página inicial com mensagem de erro
|
||||
header('Location: /?message=' . $errorType);
|
||||
exit;
|
||||
}
|
||||
} else {
|
||||
// URL inválida
|
||||
// Invalid URL / URL inválida
|
||||
header('Location: /?message=INVALID_URL');
|
||||
exit;
|
||||
}
|
||||
} else {
|
||||
// Path inválido
|
||||
// Invalid path / Path inválido
|
||||
header('Location: /?message=NOT_FOUND');
|
||||
exit;
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue