2026-06-02 13:47:36 -05:00
<? php
/**
* @package MokoJoomBackup
2026-06-06 14:52:27 -05:00
* @subpackage com_mokojoombackup
2026-06-02 13:47:36 -05:00
* @author Moko Consulting <hello@mokoconsulting.tech>
* @copyright Copyright (C) 2026 Moko Consulting. All rights reserved.
* @license GNU General Public License version 3 or later; see LICENSE
*/
2026-06-06 14:52:27 -05:00
namespace Joomla\Component\MokoJoomBackup\Administrator\Table ;
2026-06-02 13:47:36 -05:00
defined ( '_JEXEC' ) or die ;
use Joomla\CMS\Table\Table ;
use Joomla\Database\DatabaseDriver ;
class ProfileTable extends Table
{
public function __construct ( DatabaseDriver $db )
{
2026-06-06 14:52:27 -05:00
parent :: __construct ( '#__mokojoombackup_profiles' , 'id' , $db );
2026-06-02 13:47:36 -05:00
}
2026-06-07 06:54:12 -05:00
public function store ( $updateNulls = true ) : bool
{
$result = parent :: store ( $updateNulls );
if ( $result && ! empty ( $this -> backup_dir )) {
$this -> protectWebAccessibleDir ( $this -> backup_dir );
}
return $result ;
}
private function protectWebAccessibleDir ( string $dir ) : void
{
// Resolve [DEFAULT_DIR] placeholder
$defaultDir = JPATH_ADMINISTRATOR . '/components/com_mokojoombackup/backups' ;
$resolved = str_replace ( '[DEFAULT_DIR]' , $defaultDir , $dir );
// Resolve relative paths from JPATH_ROOT
if ( $resolved !== '' && $resolved [ 0 ] !== '/' && ! preg_match ( '#^[A-Za-z]:[/\\\\]#' , $resolved )) {
$resolved = JPATH_ROOT . '/' . $resolved ;
}
// Skip if unresolved placeholders remain
if ( preg_match ( '/\[.+\]/' , $resolved )) {
return ;
}
// Only protect directories under the web root
$jRoot = realpath ( JPATH_ROOT ) ?: JPATH_ROOT ;
$realDir = realpath ( $resolved ) ?: $resolved ;
if ( strpos ( $realDir , $jRoot ) !== 0 ) {
return ;
}
if ( ! is_dir ( $resolved )) {
@ mkdir ( $resolved , 0755 , true );
}
if ( is_dir ( $resolved )) {
$htaccess = $resolved . '/.htaccess' ;
if ( ! is_file ( $htaccess )) {
2026-06-07 09:17:20 -05:00
if ( @ file_put_contents ( $htaccess , "# Apache 2.4+ \n <IfModule mod_authz_core.c> \n Require all denied \n </IfModule> \n # Apache 2.2 \n <IfModule !mod_authz_core.c> \n Order deny,allow \n Deny from all \n </IfModule> \n " ) === false ) {
2026-06-07 09:11:39 -05:00
error_log ( 'MokoJoomBackup: Could not create .htaccess in: ' . $resolved );
}
2026-06-07 06:54:12 -05:00
}
$index = $resolved . '/index.html' ;
if ( ! is_file ( $index )) {
2026-06-07 09:11:39 -05:00
if ( @ file_put_contents ( $index , '<!DOCTYPE html><title></title>' ) === false ) {
error_log ( 'MokoJoomBackup: Could not create index.html in: ' . $resolved );
}
2026-06-07 06:54:12 -05:00
}
}
}
2026-06-02 13:47:36 -05:00
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' ;
}
$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 ;
}
}