Commit inicial - WordPress Análisis de Precios Unitarios

- WordPress core y plugins
- Tema Twenty Twenty-Four configurado
- Plugin allow-unfiltered-html.php simplificado
- .gitignore configurado para excluir wp-config.php y uploads

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
root
2025-11-03 21:04:30 -06:00
commit a22573bf0b
24068 changed files with 4993111 additions and 0 deletions

View File

@@ -0,0 +1,192 @@
<?php
class Red_Apache_File extends Red_FileIO {
public function force_download() {
parent::force_download();
header( 'Content-Type: application/octet-stream' );
header( 'Content-Disposition: attachment; filename="' . $this->export_filename( 'htaccess' ) . '"' );
}
public function get_data( array $items, array $groups ) {
include_once dirname( dirname( __FILE__ ) ) . '/models/htaccess.php';
$htaccess = new Red_Htaccess();
foreach ( $items as $item ) {
$htaccess->add( $item );
}
return $htaccess->get() . PHP_EOL;
}
public function load( $group, $filename, $data ) {
// Remove any comments
$data = str_replace( "\n", "\r", $data );
// Split it into lines
$lines = array_filter( explode( "\r", $data ) );
$count = 0;
foreach ( (array) $lines as $line ) {
$item = $this->get_as_item( $line );
if ( $item ) {
$item['group_id'] = $group;
$redirect = Red_Item::create( $item );
if ( ! is_wp_error( $redirect ) ) {
$count++;
}
}
}
return $count;
}
public function get_as_item( $line ) {
$item = false;
if ( preg_match( '@rewriterule\s+(.*?)\s+(.*?)\s+(\[.*\])*@i', $line, $matches ) > 0 ) {
$item = array(
'url' => $this->regex_url( $matches[1] ),
'match_type' => 'url',
'action_type' => 'url',
'action_data' => array( 'url' => $this->decode_url( $matches[2] ) ),
'action_code' => $this->get_code( $matches[3] ),
'regex' => $this->is_regex( $matches[1] ),
);
} elseif ( preg_match( '@Redirect\s+(.*?)\s+"(.*?)"\s+(.*)@i', $line, $matches ) > 0 || preg_match( '@Redirect\s+(.*?)\s+(.*?)\s+(.*)@i', $line, $matches ) > 0 ) {
$item = array(
'url' => $this->decode_url( $matches[2] ),
'match_type' => 'url',
'action_type' => 'url',
'action_data' => array( 'url' => $this->decode_url( $matches[3] ) ),
'action_code' => $this->get_code( $matches[1] ),
);
} elseif ( preg_match( '@Redirect\s+"(.*?)"\s+(.*)@i', $line, $matches ) > 0 || preg_match( '@Redirect\s+(.*?)\s+(.*)@i', $line, $matches ) > 0 ) {
$item = array(
'url' => $this->decode_url( $matches[1] ),
'match_type' => 'url',
'action_type' => 'url',
'action_data' => array( 'url' => $this->decode_url( $matches[2] ) ),
'action_code' => 302,
);
} elseif ( preg_match( '@Redirectmatch\s+(.*?)\s+(.*?)\s+(.*)@i', $line, $matches ) > 0 ) {
$item = array(
'url' => $this->decode_url( $matches[2] ),
'match_type' => 'url',
'action_type' => 'url',
'action_data' => array( 'url' => $this->decode_url( $matches[3] ) ),
'action_code' => $this->get_code( $matches[1] ),
'regex' => true,
);
} elseif ( preg_match( '@Redirectmatch\s+(.*?)\s+(.*)@i', $line, $matches ) > 0 ) {
$item = array(
'url' => $this->decode_url( $matches[1] ),
'match_type' => 'url',
'action_type' => 'url',
'action_data' => array( 'url' => $this->decode_url( $matches[2] ) ),
'action_code' => 302,
'regex' => true,
);
}
if ( $item ) {
$item['action_type'] = 'url';
$item['match_type'] = 'url';
if ( $item['action_code'] === 0 ) {
$item['action_type'] = 'pass';
}
return $item;
}
return false;
}
private function decode_url( $url ) {
$url = rawurldecode( $url );
// Replace quoted slashes
$url = preg_replace( '@\\\/@', '/', $url );
// Ensure escaped '.' is still escaped
$url = preg_replace( '@\\\\.@', '\\\\.', $url );
return $url;
}
private function is_str_regex( $url ) {
$regex = '()[]$^?+.';
$escape = false;
$len = strlen( $url );
for ( $x = 0; $x < $len; $x++ ) {
$escape = false;
$char = substr( $url, $x, 1 );
if ( $char === '\\' ) {
$escape = true;
} elseif ( strpos( $regex, $char ) !== false && ! $escape ) {
return true;
}
}
return false;
}
private function is_regex( $url ) {
if ( $this->is_str_regex( $url ) ) {
$tmp = ltrim( $url, '^' );
$tmp = rtrim( $tmp, '$' );
if ( $this->is_str_regex( $tmp ) ) {
return true;
}
}
return false;
}
private function regex_url( $url ) {
$url = $this->decode_url( $url );
if ( $this->is_str_regex( $url ) ) {
$tmp = ltrim( $url, '^' );
$tmp = rtrim( $tmp, '$' );
if ( $this->is_str_regex( $tmp ) ) {
return '^/' . ltrim( $tmp, '/' );
}
return '/' . ltrim( $tmp, '/' );
}
return $this->decode_url( $url );
}
private function get_code( $code ) {
if ( strpos( $code, '301' ) !== false || stripos( $code, 'permanent' ) !== false ) {
return 301;
}
if ( strpos( $code, '302' ) !== false ) {
return 302;
}
if ( strpos( $code, '307' ) !== false || stripos( $code, 'seeother' ) !== false ) {
return 307;
}
if ( strpos( $code, '404' ) !== false || stripos( $code, 'forbidden' ) !== false || strpos( $code, 'F' ) !== false ) {
return 404;
}
if ( strpos( $code, '410' ) !== false || stripos( $code, 'gone' ) !== false || strpos( $code, 'G' ) !== false ) {
return 410;
}
return 302;
}
}

View File

@@ -0,0 +1,172 @@
<?php
class Red_Csv_File extends Red_FileIO {
const CSV_SOURCE = 0;
const CSV_TARGET = 1;
const CSV_REGEX = 2;
const CSV_CODE = 3;
public function force_download() {
parent::force_download();
header( 'Content-Type: text/csv' );
header( 'Content-Disposition: attachment; filename="' . $this->export_filename( 'csv' ) . '"' );
}
public function get_data( array $items, array $groups ) {
$lines = [ implode( ',', array( 'source', 'target', 'regex', 'code', 'type', 'hits', 'title', 'status' ) ) ];
foreach ( $items as $line ) {
$lines[] = $this->item_as_csv( $line );
}
return implode( PHP_EOL, $lines ) . PHP_EOL;
}
public function item_as_csv( $item ) {
$data = $item->match->get_data();
if ( isset( $data['url'] ) ) {
$data = $data['url'];
} else {
$data = '/unknown';
}
if ( $item->get_action_code() > 400 && $item->get_action_code() < 500 ) {
$data = '';
}
$csv = array(
$item->get_url(),
$data,
$item->is_regex() ? 1 : 0,
$item->get_action_code(),
$item->get_action_type(),
$item->get_hits(),
$item->get_title(),
$item->is_enabled() ? 'active' : 'disabled',
);
$csv = array_map( array( $this, 'escape_csv' ), $csv );
return implode( ',', $csv );
}
public function escape_csv( $item ) {
if ( is_numeric( $item ) ) {
return $item;
}
return '"' . str_replace( '"', '""', $item ) . '"';
}
public function load( $group, $filename, $data ) {
$file = fopen( $filename, 'r' );
if ( $file ) {
$separators = [
',',
';',
'|',
];
foreach ( $separators as $separator ) {
fseek( $file, 0 );
$count = $this->load_from_file( $group, $file, $separator );
if ( $count > 0 ) {
return $count;
}
}
}
return 0;
}
public function load_from_file( $group_id, $file, $separator ) {
global $wpdb;
$count = 0;
$group = Red_Group::get( $group_id );
if ( ! $group ) {
return 0;
}
while ( ( $csv = fgetcsv( $file, 5000, $separator ) ) ) {
$item = $this->csv_as_item( $csv, $group );
if ( $item && $this->item_is_valid( $item ) ) {
$created = Red_Item::create( $item );
// The query log can use up all the memory
$wpdb->queries = [];
if ( ! is_wp_error( $created ) ) {
$count++;
}
}
}
return $count;
}
private function item_is_valid( array $csv ) {
if ( strlen( $csv['url'] ) === 0 ) {
return false;
}
if ( $csv['action_data']['url'] === $csv['url'] ) {
return false;
}
return true;
}
private function get_valid_code( $code ) {
if ( get_status_header_desc( $code ) !== '' ) {
return intval( $code, 10 );
}
return 301;
}
private function get_action_type( $code ) {
if ( $code > 400 && $code < 500 ) {
return 'error';
}
return 'url';
}
public function csv_as_item( $csv, Red_Group $group ) {
if ( count( $csv ) > 1 && $csv[ self::CSV_SOURCE ] !== 'source' && $csv[ self::CSV_TARGET ] !== 'target' ) {
$code = isset( $csv[ self::CSV_CODE ] ) ? $this->get_valid_code( $csv[ self::CSV_CODE ] ) : 301;
return array(
'url' => trim( $csv[ self::CSV_SOURCE ] ),
'action_data' => array( 'url' => trim( $csv[ self::CSV_TARGET ] ) ),
'regex' => isset( $csv[ self::CSV_REGEX ] ) ? $this->parse_regex( $csv[ self::CSV_REGEX ] ) : $this->is_regex( $csv[ self::CSV_SOURCE ] ),
'group_id' => $group->get_id(),
'match_type' => 'url',
'action_type' => $this->get_action_type( $code ),
'action_code' => $code,
'status' => $group->is_enabled() ? 'enabled' : 'disabled',
);
}
return false;
}
private function parse_regex( $value ) {
return intval( $value, 10 ) === 1 ? true : false;
}
private function is_regex( $url ) {
$regex = '()[]$^*';
if ( strpbrk( $url, $regex ) === false ) {
return false;
}
return true;
}
}

View File

@@ -0,0 +1,84 @@
<?php
class Red_Json_File extends Red_FileIO {
public function force_download() {
parent::force_download();
header( 'Content-Type: application/json' );
header( 'Content-Disposition: attachment; filename="' . $this->export_filename( 'json' ) . '"' );
}
public function get_data( array $items, array $groups ) {
$version = red_get_plugin_data( dirname( dirname( __FILE__ ) ) . '/redirection.php' );
$items = array(
'plugin' => array(
'version' => trim( $version['Version'] ),
'date' => date( 'r' ),
),
'groups' => $groups,
'redirects' => array_map( function( $item ) {
return $item->to_json();
}, $items ),
);
return wp_json_encode( $items, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES ) . PHP_EOL;
}
public function load( $group, $filename, $data ) {
global $wpdb;
$count = 0;
$json = @json_decode( $data, true );
if ( $json === false ) {
return 0;
}
// Import groups
$group_map = array();
if ( isset( $json['groups'] ) ) {
foreach ( $json['groups'] as $group ) {
$old_group_id = $group['id'];
unset( $group['id'] );
$group = Red_Group::create( $group['name'], $group['module_id'], $group['enabled'] ? true : false );
if ( $group ) {
$group_map[ $old_group_id ] = $group->get_id();
}
}
}
unset( $json['groups'] );
// Import redirects
if ( isset( $json['redirects'] ) ) {
foreach ( $json['redirects'] as $pos => $redirect ) {
unset( $redirect['id'] );
if ( ! isset( $group_map[ $redirect['group_id'] ] ) ) {
$new_group = Red_Group::create( 'Group', 1 );
$group_map[ $redirect['group_id'] ] = $new_group->get_id();
}
if ( $redirect['match_type'] === 'url' && isset( $redirect['action_data'] ) && ! is_array( $redirect['action_data'] ) ) {
$redirect['action_data'] = array( 'url' => $redirect['action_data'] );
}
$redirect['group_id'] = $group_map[ $redirect['group_id'] ];
$created = Red_Item::create( $redirect );
if ( $created instanceof Red_Item ) {
$count++;
}
// Helps reduce memory usage
unset( $json['redirects'][ $pos ] );
$wpdb->queries = array();
$wpdb->num_queries = 0;
}
}
return $count;
}
}

View File

@@ -0,0 +1,114 @@
<?php
class Red_Nginx_File extends Red_FileIO {
public function force_download() {
parent::force_download();
header( 'Content-Type: application/octet-stream' );
header( 'Content-Disposition: attachment; filename="' . $this->export_filename( 'nginx' ) . '"' );
}
public function get_data( array $items, array $groups ) {
$lines = array();
$version = red_get_plugin_data( dirname( dirname( __FILE__ ) ) . '/redirection.php' );
$lines[] = '# Created by Redirection';
$lines[] = '# ' . date( 'r' );
$lines[] = '# Redirection ' . trim( $version['Version'] ) . ' - https://redirection.me';
$lines[] = '';
$lines[] = 'server {';
$parts = array();
foreach ( $items as $item ) {
if ( $item->is_enabled() ) {
$parts[] = $this->get_nginx_item( $item );
}
}
$lines = array_merge( $lines, array_filter( $parts ) );
$lines[] = '}';
$lines[] = '';
$lines[] = '# End of Redirection';
return implode( PHP_EOL, $lines ) . PHP_EOL;
}
private function get_redirect_code( Red_Item $item ) {
if ( $item->get_action_code() === 301 ) {
return 'permanent';
}
return 'redirect';
}
public function load( $group, $data, $filename = '' ) {
return 0;
}
private function get_nginx_item( Red_Item $item ) {
$target = 'add_' . $item->get_match_type();
if ( method_exists( $this, $target ) ) {
return ' ' . $this->$target( $item, $item->get_match_data() );
}
return false;
}
private function add_url( Red_Item $item, array $match_data ) {
return $this->get_redirect( $item->get_url(), $item->get_action_data(), $this->get_redirect_code( $item ), $match_data['source'], $item->source_flags->is_regex() );
}
private function add_agent( Red_Item $item, array $match_data ) {
if ( $item->match->url_from ) {
$lines[] = 'if ( $http_user_agent ~* ^' . $item->match->user_agent . '$ ) {';
$lines[] = ' ' . $this->get_redirect( $item->get_url(), $item->match->url_from, $this->get_redirect_code( $item ), $match_data['source'] );
$lines[] = ' }';
}
if ( $item->match->url_notfrom ) {
$lines[] = 'if ( $http_user_agent !~* ^' . $item->match->user_agent . '$ ) {';
$lines[] = ' ' . $this->get_redirect( $item->get_url(), $item->match->url_notfrom, $this->get_redirect_code( $item ), $match_data['source'] );
$lines[] = ' }';
}
return implode( "\n", $lines );
}
private function add_referrer( Red_Item $item, array $match_data ) {
if ( $item->match->url_from ) {
$lines[] = 'if ( $http_referer ~* ^' . $item->match->referrer . '$ ) {';
$lines[] = ' ' . $this->get_redirect( $item->get_url(), $item->match->url_from, $this->get_redirect_code( $item ), $match_data['source'] );
$lines[] = ' }';
}
if ( $item->match->url_notfrom ) {
$lines[] = 'if ( $http_referer !~* ^' . $item->match->referrer . '$ ) {';
$lines[] = ' ' . $this->get_redirect( $item->get_url(), $item->match->url_notfrom, $this->get_redirect_code( $item ), $match_data['source'] );
$lines[] = ' }';
}
return implode( "\n", $lines );
}
private function get_redirect( $line, $target, $code, $source, $regex = false ) {
$line = ltrim( $line, '^' );
$line = rtrim( $line, '$' );
$source_url = new Red_Url_Encode( $line, $regex );
$target_url = new Red_Url_Encode( $target );
// Remove any existing start/end from a regex
$from = $source_url->get_as_source();
$from = ltrim( $from, '^' );
$from = rtrim( $from, '$' );
if ( isset( $source['flag_case'] ) && $source['flag_case'] ) {
$from = '(?i)^' . $from;
} else {
$from = '^' . $from;
}
return 'rewrite ' . $from . '$ ' . $target_url->get_as_target() . ' ' . $code . ';';
}
}

View File

@@ -0,0 +1,47 @@
<?php
class Red_Rss_File extends Red_FileIO {
public function force_download() {
header( 'Content-type: text/xml; charset=' . get_option( 'blog_charset' ), true );
}
public function get_data( array $items, array $groups ) {
$xml = '<?xml version="1.0" encoding="' . get_option( 'blog_charset' ) . '"?' . ">\r\n";
ob_start();
?>
<rss version="2.0"
xmlns:content="http://purl.org/rss/1.0/modules/content/"
xmlns:wfw="http://wellformedweb.org/CommentAPI/"
xmlns:dc="http://purl.org/dc/elements/1.1/">
<channel>
<title>Redirection - <?php bloginfo_rss( 'name' ); ?></title>
<link><?php esc_url( bloginfo_rss( 'url' ) ); ?></link>
<description><?php esc_html( bloginfo_rss( 'description' ) ); ?></description>
<pubDate><?php echo esc_html( mysql2date( 'D, d M Y H:i:s +0000', get_lastpostmodified( 'GMT' ), false ) ); ?></pubDate>
<generator>
<?php echo esc_html( 'http://wordpress.org/?v=' ); ?>
<?php bloginfo_rss( 'version' ); ?>
</generator>
<language><?php echo esc_html( get_option( 'rss_language' ) ); ?></language>
<?php foreach ( $items as $log ) : ?>
<item>
<title><?php echo esc_html( $log->get_url() ); ?></title>
<link><![CDATA[<?php echo esc_url( home_url() ) . esc_url( $log->get_url() ); ?>]]></link>
<pubDate><?php echo esc_html( date( 'D, d M Y H:i:s +0000', intval( $log->get_last_hit(), 10 ) ) ); ?></pubDate>
<guid isPermaLink="false"><?php echo esc_html( $log->get_id() ); ?></guid>
<description><?php echo esc_html( $log->get_url() ); ?></description>
</item>
<?php endforeach; ?>
</channel>
</rss>
<?php
$xml .= ob_get_contents();
ob_end_clean();
return $xml;
}
function load( $group, $data, $filename = '' ) {
}
}