HEX
Server: Apache/2.4.58 (Ubuntu)
System: Linux Bradford-Sitios 6.14.0-1017-azure #17~24.04.1-Ubuntu SMP Mon Dec 1 20:10:50 UTC 2025 x86_64
User: www-data (33)
PHP: 7.4.33
Disabled: pcntl_alarm,pcntl_fork,pcntl_waitpid,pcntl_wait,pcntl_wifexited,pcntl_wifstopped,pcntl_wifsignaled,pcntl_wifcontinued,pcntl_wexitstatus,pcntl_wtermsig,pcntl_wstopsig,pcntl_signal,pcntl_signal_get_handler,pcntl_signal_dispatch,pcntl_get_last_error,pcntl_strerror,pcntl_sigprocmask,pcntl_sigwaitinfo,pcntl_sigtimedwait,pcntl_exec,pcntl_getpriority,pcntl_setpriority,pcntl_async_signals,pcntl_unshare,
Upload Files
File: /var/www/proveedores.bradford/application/controllers/ProviderController.php
<?php
class ProviderController extends CI_Controller
{
	function  __construct()
	{
		parent::__construct();
		$this->load->helper('utilities_helper');
		$this->load->helper(HELPER_MODEL);
		$this->load->helper('debug_helper');

		$this->load->helper('date');
		$this->load->library('session');
		$this->load->library('email');
		define('LAYOUT', 'layout');
	}

	function index($value = '')
	{
		$data['regiones'] = get_table('regiones');
		$data['giros'] = get_table('giros', 'id, codigo, name', array('name' => 'asc'));
		$data['ok_email'] = $this->session->flashdata('ok_email');
		//pre($data);

		$data['main_content'] = 'admin/index_view';
		$this->load->view('shared/' . LAYOUT, $data);
	}

	function comuna_by_id($region_id)
	{
		$comunas = get_result_by_where('comunas', array('id_region' => $region_id), 'id, nombre', array('nombre' => 'asc'));
		$comunas_option = '';
		foreach ($comunas as $value) {
			$comunas_option .= '<option value="' . $value->id . '">' . $value->nombre . '</option>';
		}
		echo '
		<select name="comuna" id="comuna" required class="form-control">
			<option value="" disabled selected>Comuna</option>
			' . $comunas_option . '
		</select>
		<i class="zmdi zmdi-caret-down" style="font-size: 17px"></i>';
	}
	function register()
	{
		$post = $this->input->post();

		// Tamaño máximo en bytes (5 MB)
		$maxFileSize = 5 * 1024 * 1024;

		// Formatos permitidos (extensiones seguras)
		$allowedExtensions = [
			'jpg',
			'jpeg',
			'png',
			'webp',
			'pdf',
			'doc',
			'docx',
			'xls',
			'xlsx',
			'csv',
		];
		$allowedMimeTypes = [
			'image/jpeg',
			'image/png',
			'image/webp',
			'application/pdf',
			'application/msword',                         // .doc
			'application/vnd.openxmlformats-officedocument.wordprocessingml.document', // .docx
			'application/vnd.ms-excel',                  // .xls
			'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', // .xlsx
			'text/csv',                                  // .csv
		];
		if (!empty($post)) {
			$errorFile = [];
			if (!empty($_FILES['files'])) {
				foreach ($_FILES['files']['tmp_name'] as $key => $tmpName) {
					// Verificar si el archivo está vacío
					if (empty($tmpName) || $_FILES['files']['size'][$key] == 0) {
						$errorFile[] = 'El archivo está vacío o no se subió correctamente.';
						continue; // Pasar al siguiente archivo
					}

					$extensionFile = strtolower(pathinfo($_FILES['files']['name'][$key], PATHINFO_EXTENSION));
					$mimeType = mime_content_type($tmpName); // Detectar el tipo MIME real del archivo
					$fileSize = $_FILES['files']['size'][$key]; // Tamaño del archivo en bytes

					// Validar extensión, MIME type y tamaño del archivo
					if (!in_array($extensionFile, $allowedExtensions) || !in_array($mimeType, $allowedMimeTypes)) {
						$errorFile[] = 'El archivo "' . $_FILES['files']['name'][$key] . '" posee una extensión inválida.';
					} elseif ($fileSize > $maxFileSize) {
						$errorFile[] = 'El archivo "' . $_FILES['files']['name'][$key] . '" excede el tamaño máximo permitido de 5 MB.';
					}
				}
			}

			if (!empty($errorFile)) {
				$this->session->set_flashdata('ok_email', 'Se encontraron los siguientes errores: ' . implode(', ', $errorFile));
				redirect(base_url());
			}

			// Capturar datos del formulario
			$name = $this->input->post('nombre');
			$email = $this->input->post('email');
			$company = $this->input->post('empresa');
			$rut = $this->input->post('rut');
			$phone = $this->input->post('telefono');
			$comment = $this->input->post('comentarios');
			$giro = $this->input->post('giro');
			$region = $this->input->post('region');
			$commune = $this->input->post('comuna');
			// Validar que 'name' no esté vacío y tenga al menos 3 caracteres
			if (empty($name) || strlen($name) < 3) {
				$errorData[] = 'El nombre debe tener al menos 3 caracteres y no puede estar vacío.';
			}

			// Validar que 'email' sea un correo válido
			if (empty($email) || !filter_var($email, FILTER_VALIDATE_EMAIL)) {
				$errorData[] = 'El correo electrónico no es válido o está vacío.';
			}

			// Validar que 'empresa' no esté vacío
			if (empty($company) || strlen($name) < 3) {
				$errorData[] = 'La empresa debe tener al menos 3 caracteres y no puede estar vacío.';
			}

			// Validar que 'rut' tenga un formato válido (ejemplo: XX.XXX.XXX-X o XXXXXXXXX)
			if (empty($rut) || !preg_match('/^\d{1,2}\.?\d{3}\.?\d{3}-?[0-9kK]$/', $rut)) {
				$errorData[] = 'El RUT no es válido o está vacío.';
			}

			// Validar que 'telefono' tenga solo números y al menos 8 caracteres
			if (empty($phone)) {
				$errorData[] = 'El teléfono no puede estar vacío.';
			}

			if (empty($giro) || $giro < 1) {
				$errorData[] = 'El giro no puede estar vacío.';
			}

			if (empty($region) || $region < 1) {
				$errorData[] = 'La region no puede estar vacía.';
			}

			if (empty($commune) || $commune < 1) {
				$errorData[] = 'La comuna no puede estar vacía.';
			}

			// Nota: No se valida 'comentarios', ya que puede estar vacío o contener cualquier valor.
			// Mostrar errores si existen
			if (!empty($errorData)) {
				$this->session->set_flashdata('ok_email', 'Errores encontrados: ' . implode(' | ', $errorData));
				redirect(base_url(''));
			}

			$giroData =   get_row_by_where('giros',    ['id' => $giro]);
			$regionData = get_row_by_where('regiones', ['id' => $region]);
			$comunaData = get_row_by_where('comunas',  ['id' => $commune]);
			$contactoId = insert('contactos', $post);

			if (!empty($_FILES['files'])) {
				$ruta_archivo = ROOT_PATH_BASE . "/contact_files/$contactoId";
				if (is_dir($ruta_archivo) === FALSE) {
					mkdir($ruta_archivo, 0755, TRUE);
				}
				foreach ($_FILES['files']['tmp_name'] as $key => $value) {
					$nombre_archivo = $_FILES['files']['name'][$key];
					$destino = "$ruta_archivo/$nombre_archivo";

					// Validar si el archivo subido tiene contenido
					if (empty($value) || $_FILES['files']['size'][$key] == 0) {
						continue;
					}

					if (!is_uploaded_file($value)) {
						echo("El archivo $value no es un archivo válido subido por PHP.");
						continue;
					}

					// Copiar archivo
					if (move_uploaded_file($value, $destino)) {
						$files_attach[$key] = [
							'file_name' => $nombre_archivo,
							'path' => $destino,
							'type' => mime_content_type($destino)
						];
					} else {
						$error = error_get_last();
						echo ("Error al mover el archivo $nombre_archivo desde $value a $destino. Detalle: " . json_encode($error));
					}
				}
			}


			update_row_by_where('contactos', array('archivos' => json_encode($files_attach)), array('id' => $contactoId));
			$html = $this->load->view('email/contact_view', [
				'main_content' => $this->contentMail($post, $regionData, $giroData, $comunaData)
			], TRUE);

			$data = [
				'para' => $_ENV['DESTINATARIO_EMAIL'],
				'remitente' => $_ENV['REMITENTE_BASE'],
				'usuario' => $_ENV['USUARIO_MAIL_BASE'],
				'bcc_remitente' => $_ENV['BCC_REMITENTE'],
				'asunto' => 'Nuevo contacto formulario proveedores ' . date('d-m-Y'),
				'attach' => $files_attach,
				'mensaje' => $html
			];
			$result = enviarCorreoMailBrevo($data);
			$this->session->set_flashdata('ok_email', 'Su mensaje ha sido registrado correctamente, nos comunicaremos a la brevedad');
			redirect(base_url());
		}
		$this->session->set_flashdata('ok_email', 'Método inválido');
		redirect(base_url());
	}

	private function contentMail($post = array(), $region, $giro, $comuna)
	{
		return
			"
			<p>Buenos días</p><br>
			<p>Le informamos que hemos recibido una nueva solicitud de registro como proveedor a través de nuestro formulario web. A continuación, se detallan los datos del contacto</p>
			<p><b>Nombre contacto : </b> $post[nombre]</p>
			<p><b>Email : </b> $post[email]</p>
			<p><b>Empresa : </b> $post[empresa]</p>
			<p><b>Rut : </b> $post[rut]</p>
			<p><b>Teléfono : </b> $post[telefono]</p>
			<p><b>Giro : </b>($giro->codigo) $giro->name</p>
			<p><b>Región : </b> $region->name</p>
			<p><b>Comuna : </b> $comuna->nombre</p>
			<p><b>Comentarios : </b> $post[comentarios]</p><br>
		";
	}

	public function report()
	{
		$query = $this->db->query("select contactos.id, contactos.nombre, email, empresa, rut, telefono, `giros`.`name`, `regiones`.`name`, comunas.nombre, comentarios, archivos, contactos.fecha_creacion
                        from contactos
                        inner join regiones on regiones.id = contactos.region
                        inner join comunas on comunas.id_region = regiones.id
                        inner join giros on giros.id = contactos.giro")->result();

		if (empty($query)) {
			$this->session->set_flashdata('ok_email', 'No existe data a exportar');
			redirect(base_url());
		}

		reportExcel($query, 'reporte_contactos_' . date('Ymd_His'), '');
	}
}