PTS rates-crm - Auditoria y reparacion (25/09/2026)
====================================================
Compatible con PHP 7.2 a 8.4. Probado con PHP 8.4 + MariaDB 10.11 (stored procedures simulados):
todas las funciones A, C, D, F, G, J, K, L, M, N, O, P responden "1" y generan sus emails;
los 28 formularios/grillas cargan sin errores.

CAUSA PRINCIPAL DE LA FALLA
---------------------------
El codigo fue escrito para PHP 7.2 (ea-php72). En PHP 8:
 1. Operaciones con valores vacios ("" * 2, "" + 0, number_format("")) lanzan TypeError fatal.
    La generacion de la plantilla de cotizacion (noches adicionales vacias, niños vacios) moria
    DESPUES de registrar la cotizacion: el cliente veia el boton bloqueado, sin email.
 2. display_errors=1: cualquier Warning se imprimia antes del "1" y el JavaScript no lo reconocia.
 3. mysqli lanza excepciones por defecto (8.1+) y mysqli_affected_rows() sin conexion es fatal.
 4. trim() sobre campos array ($$key = trim($value)) es fatal.

ARCHIVOS NUEVOS
---------------
includes/php/bootstrap.php   Configuracion comun: errores al log (no en pantalla), zona horaria Lima,
                             mysqli sin excepciones, ruta de sesiones valida, funciones fncNum,
                             fncNumFmt, fncBlank, fncPost_Vars, fncReq, fncHtml, fncNoCRLF.

CAMBIOS POR ARCHIVO
-------------------
config-a.php / config-x.php
 - Carga bootstrap.php. Nuevas constantes SMTP_* y MAIL_FROM_DEFAULT (la clave de Gmail ya no esta en el codigo).
 - >>> COMPLETAR SMTP_PASS con una "Contraseña de aplicacion" de Google. Mientras este vacio se usa mail() del servidor.

clase.bdmysql-a.php / -x.php (misma interfaz)
 - Verifica la conexion antes de set_charset; utf8mb4.
 - Vacia todos los result sets de cada CALL (evita "Commands out of sync").
 - Errores SQL -> error_log y resultado vacio, sin header(Location) despues de HTML
   (8.600+ "Cannot modify header information" en el error_log antiguo).
 - Metodos esc() y num() para escapar parametros.

class.rates-a.php / -x.php
 - TODOS los parametros de los stored procedures se escapan (texto) o se convierten a numero:
   se cierra la inyeccion SQL (p.ej. xP/xT/xH/p/t llegaban directo al CALL sin comillas).
 - Se quito el prefijo fijo "cuscotra_peruvian_crmv1." -> usa la BD definida en config (DB_NAME).

business.rates-a.php / business.rates-t.php (Travel to Peru; mismas correcciones)
 - Reemplazo de $$key=trim($value) por extract(fncPost_Vars(), EXTR_SKIP).
 - Calculos de tarifa, noches adicionales, niños, servicios y plantillas con fncNum/fncNumFmt.
 - BUG de montos: los servicios adicionales >= $1,000 se sumaban como $1 (la coma cortaba el numero). Corregido.
 - BUG: xF=N usaba la clase CRM() inexistente -> fatal. Ahora usa Rates().
 - BUG: xF=B llamaba a fncGet_Rooms() (comentada) -> fatal. Ahora no hace nada.
 - BUG: plantillas de Tour y Reserva Tour dejaban "V_NACIONALIDAD" en el email (usaban variable de Circuito).
 - BUG: asunto admin "CRM - Cotizacion: Solicitud de Cotizacion: ..." duplicado. Corregido.
 - Reserva Tour: nombres de pasajeros saneados (iban a SQL dinamico); tarifa por pax inicializada.
 - Circuito: categorias saneadas (iban a SQL dinamico).
 - addslashes() retirado (ahora escapa la clase Rates; evita O\'Brien en la BD).
 - Emails: asunto/nombres codificados UTF-8 (acentos), sin inyeccion de cabeceras.
   Envio SMTP con respaldo automatico a mail() si falla.

business.rates-x.php
 - Ahora delega en business.rates-a.php. La version anterior no tenia las funciones O/M,
   por eso form-cotizador-i.php no registraba nada. form-cotizador-i apunta ahora a business.rates-a.php.

Formularios (form-*.php) y grillas (grid-*.php)
 - Cargan bootstrap.php (antes de session_start).
 - Parametros p, c, t convertidos a entero; u escapado: se cierra XSS (p.ej. ?p=1;alert(1)).
 - Formularios paso 2 (*-customer, tour-reserva-pax): valores reenviados escapados en HTML;
   $$key global reemplazado (podia sobrescribir $_SESSION).
 - form-tour-customer: suma de pasajeros y total sin TypeError.

includes/php/error.php
 - Ya no imprime el texto recibido por URL (XSS).

includes/phpmailer/class.phpmailer.php (5.2.15)
 - get_magic_quotes_runtime() protegido (no existe en PHP 8).
 - Mitigacion CVE-2016-10033/10045 en mailSend(). Recomendado a futuro: PHPMailer 6.x.

ACCIONES MANUALES EN EL SERVIDOR (IMPORTANTE)
---------------------------------------------
1. BORRAR del servidor (se sirven como texto plano y exponen contraseñas de BD / Gmail):
   includes/php/config-a.php_20210212
   includes/php/business.rates-a.php_20201126
   includes/php/business.rates-a.php_20210212
   includes/php/class.rates-a.php_20210212
   form-oferta.php_20201011
2. BORRAR copias antiguas accesibles publicamente:
   form-cotizador-a_bk.php, form-cotizador-n_bk.php, form-cotizador-customer_old.php,
   includes/php/business.rates-a_bk.php, error_log, includes/phpmailer/error_log
3. CAMBIAR la contraseña de la BD (cuscotra_usr_crm) y de la cuenta Gmail peruviantravelservice.crm
   (han estado expuestas en los archivos del punto 1). Actualizar config-a.php.
4. Crear App Password de Google y colocarla en SMTP_PASS (config-a.php).
5. Recomendado: SPF/DKIM del dominio para mail() (hoy se envia "From: counter@peruviantravelservice.com"
   desde el servidor de cuscotravels.pe -> alto riesgo de SPAM).
