* @copyright Copyright (C) 2026 Moko Consulting. All rights reserved. * @license GNU General Public License version 3 or later; see LICENSE */ namespace Joomla\Component\MokoSuiteBackup\Administrator\Table; defined('_JEXEC') or die; use Joomla\CMS\Table\Table; use Joomla\Component\MokoSuiteBackup\Administrator\Utility\BackupDirectory; use Joomla\Database\DatabaseDriver; class ProfileTable extends Table { public function __construct(DatabaseDriver $db) { parent::__construct('#__mokosuitebackup_profiles', 'id', $db); } public function store($updateNulls = true): bool { /* Handle SSH key sentinel — when __KEEP_EXISTING__ is submitted, preserve the current DB value instead of overwriting with the sentinel. This prevents the key from being exposed in the form HTML. */ if (isset($this->sftp_key_data) && $this->sftp_key_data === '__KEEP_EXISTING__') { if ($this->id) { $db = $this->getDbo(); $query = $db->getQuery(true) ->select($db->quoteName('sftp_key_data')) ->from($db->quoteName($this->_tbl)) ->where($db->quoteName('id') . ' = ' . (int) $this->id); $db->setQuery($query); $this->sftp_key_data = $db->loadResult() ?: ''; } else { $this->sftp_key_data = ''; } } $result = parent::store($updateNulls); if ($result && !empty($this->backup_dir)) { $this->protectWebAccessibleDir($this->backup_dir); } return $result; } private function protectWebAccessibleDir(string $dir): void { $resolved = BackupDirectory::resolve($dir); if (BackupDirectory::hasPlaceholders($resolved)) { return; } if (!BackupDirectory::isWebAccessible($resolved)) { return; } BackupDirectory::ensureReady($resolved); } public function check(): bool { if (empty($this->title)) { $this->setError('Profile title is required.'); return false; } if (empty($this->backup_type)) { $this->backup_type = 'full'; } // Normalize backup_dir to portable placeholder form if (!empty($this->backup_dir)) { $this->backup_dir = BackupDirectory::portablize($this->backup_dir); } $now = date('Y-m-d H:i:s'); if (empty($this->created) || $this->created === '0000-00-00 00:00:00') { $this->created = $now; } $this->modified = $now; return true; } }