shell bypass 403
<?php
/**
* @package RSForm! Pro
* @copyright (C) 2007-2019 www.rsjoomla.com
* @license GPL, http://www.gnu.org/copyleft/gpl.html
*/
defined('_JEXEC') or die;
use Joomla\CMS\Factory;
require_once __DIR__.'/helper.php';
class RSFormProBackupSubmissions
{
// Database instance
protected $db;
// Holds the form ID.
protected $id;
// Limit start for SQL query.
protected $limitstart;
// Limit for SQL query.
protected $limit;
// Position of 512-bytes TAR dummy header.
protected $header = 0;
// The path to the backup archive.
protected $path;
// The XML Writer object
protected $xml;
public function __construct($options = array()) {
require_once __DIR__.'/xml.php';
// Setup options
$this->path = $options['path'];
$this->id = $options['form'];
$this->limitstart = $options['start'];
$this->header = $options['header'];
$this->limit = !empty($options['limit']) ? $options['limit'] : 100;
// Initialize classes
$this->db = Factory::getDbo();
$this->xml = new RSFormProBackupXML;
}
public function store() {
$archive = new RSFormProTar($this->path);
$db = &$this->db;
$done = false;
// Set the data XML file number
if ($this->limitstart >= $this->limit) {
$xmlNumber = round($this->limitstart / $this->limit);
} else {
$xmlNumber = 0;
}
// Grab the submissions
$query = $db->getQuery(true);
$query->select('*')
->from($db->qn('#__rsform_submissions'))
->where($db->qn('FormId').'='.$db->q($this->id));
$db->setQuery($query, $this->limitstart, $this->limit);
if ($submissions = $db->loadObjectList('SubmissionId')) {
$query->clear()
->select('*')
->from($db->qn('#__rsform_submission_values'))
->where($db->qn('SubmissionId').' IN ('.RSFormProBackupHelper::qi(array_keys($submissions)).')');
$db->setQuery($query);
$values = $db->loadObjectList();
// Record the position
$this->header = $archive->tell();
// Add the 512-bytes dummy header
$archive->addEmptyHeader();
// Add the XML header & opening tag.
$this->xml->addHeader();
$this->xml->add('submissions');
foreach ($values as $value) {
if (empty($submissions[$value->SubmissionId]->values)) {
$submissions[$value->SubmissionId]->values = array();
}
$submissions[$value->SubmissionId]->values[$value->FieldName] = $value->FieldValue;
}
foreach ($submissions as $submission) {
$values = isset($submission->values) ? $submission->values : array();
// No need for these.
unset($submission->values, $submission->SubmissionId, $submission->FormId);
$this->xml->add('submission');
foreach ($submission as $property => $value) {
$this->xml->add($property, $value);
}
// Add values
$this->xml->add('values');
foreach ($values as $property => $value) {
$this->xml->add('value');
$this->xml->add('fieldname', $property);
$this->xml->add('fieldvalue', $value);
$this->xml->add('/value');
}
$this->xml->add('/values');
$this->xml->add('/submission');
}
// We've finished, no more submissions, add the closing tag.
$this->xml->add('/submissions');
// Add data to archive.
$archive->add((string) $this->xml);
// Compute size of current file in archive.
$size = $archive->tell() - $this->header - 512;
// Add missing padding.
$archive->addPadding($size);
// Go to header (so we can add missing header data).
$archive->seek($this->header);
// Add missing header data.
$archive->addHeader($size, RSFormProBackupHelper::getHash($this->id).'-data-'.$xmlNumber.'.xml');
} else {
// Flag so that we can move on to the next form
$done = true;
}
$archive->close();
return (object) array(
'done' => $done,
'header' => $this->header // Position of empty header (so we'll know where to overwrite it)
);
}
}