shell bypass 403

Cubjrnet7 Shell


name : form.php
<?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;
use Joomla\CMS\Table\Table;

class RSFormProRestoreForm
{
	// Database instance
	protected $db;
	
	// Holds the form's structure as a Table object
	protected $form;
	
	// Holds an array of the XML data.
	protected $xml;
	
	// Holds an array in the form of field ID => field name.
	protected $fields;
	
	// Holds the setting for keeping the form's ids from the backup
	protected $keepId;
	
	// Meta data information
	protected $metaData;
	
	public function __construct($options = array())
	{
		$this->keepId		= !empty($options['keepId']);
		$path 	  			= &$options['path'];
		$this->db 			= Factory::getDbo();
		
		// Check if the form's xml exists
		if (!file_exists($path))
		{
			throw new Exception(sprintf('The file %s does not exist!', $path));
		}
		
		if (!is_readable($path))
		{
			throw new Exception(sprintf('File %s is not readable!', $path));
		}

		// Attempt to load the XML data
		libxml_use_internal_errors(true);

		$contents = file_get_contents($path);
		if (strpos($contents, '<typeAlias>') !== false)
		{
			$contents = str_replace(array('<typeAlias></typeAlias>', '<typeAlias>', '</typeAlias>'), '', $contents);
		}
		
		if (class_exists('DOMDocument'))
		{
			$dom = new DOMDocument('1.0', 'UTF-8');
			$dom->strictErrorChecking = false;
			$dom->validateOnParse = false;
			$dom->recover = true;
			$dom->loadXML($contents);
			
			$this->xml = simplexml_import_dom($dom);
		}
		else
		{
			$this->xml = simplexml_load_string($contents);
		}
		
		if ($this->xml === false)
		{
			$errors = array();
			foreach (libxml_get_errors() as $error)
			{
				$errors[] = 'Message: '.$error->message.'; Line: '.$error->line.'; Column: '.$error->column;
			}
			throw new Exception(sprintf('Error while parsing XML: %s<br/>', implode('<br />', $errors)));
		}
		
		$this->metaData = $options['metaData'];
	}
	
	public function restore()
	{
		$this->restoreStructure();
		$this->restoreFields();
		$this->restoreCalculations();
		$this->restorePost();
		$this->restoreConditions();
		$this->restoreDirectory();
		$this->restoreEmails();
		$this->restoreMappings();
		$this->rebuildCalendarsValidationRules();
		$this->rebuildPreviewSelectFields();
		$this->rebuildGridLayout();
		
		// Allow plugins to restore their own data from the backup.
		Factory::getApplication()->triggerEvent('onRsformFormRestore', array($this->form, $this->xml, $this->fields));
	}
	
	public function getFormId()
	{
		return $this->form->FormId;
	}
	
	// Form structure
	// ==============
	
	protected function restoreStructure()
	{
		// Restore the form structure #__rsform_forms
		$data 			= array();
		$oldFormId 		= false;
		foreach ($this->xml->structure->children() as $property => $value)
		{
			// Skip translations for now
            // Skip ThemeParams, no longer exists
			if ($property == 'translations' || $property == 'ThemeParams')
			{
				continue;
			}
			
			if ($property == 'FormId')
			{
				if ($this->keepId)
				{
					$oldFormId = (string) $value;
				}

				continue;
			}
			
			$data[$property] = (string) $value;
		}
		
		$this->form = Table::getInstance('RSForm_Forms', 'Table');
		
		// Responsive layout needs its own CSS to be loaded, make sure old forms still load it when restored.
		if (version_compare($this->metaData['version'], '1.51.12', '<') && $data['FormLayoutName'] == 'responsive')
		{
			$data['LoadFormLayoutFramework'] = 1;
		}
		
		if (!$this->form->save($data))
		{
			throw new Exception(sprintf('Form %s could not be saved. Error reported is: %s', $this->form->FormTitle, $this->form->getError()));
		}

		if (!empty($oldFormId) && $oldFormId != $this->form->FormId)
		{
			// Is it free?
			$query = $this->db->getQuery(true)
				->select($this->db->qn('FormId'))
				->from($this->db->qn('#__rsform_forms'))
				->where($this->db->qn('FormId') . ' = ' . $this->db->q($oldFormId));

			// Requested form ID doesn't exist, update current form
			if (!$this->db->setQuery($query)->loadResult())
			{
				$query->clear()
					->update($this->db->qn('#__rsform_forms'))
					->set($this->db->qn('FormId') . ' = ' . $this->db->q($oldFormId))
					->where($this->db->qn('FormId') . ' = ' . $this->db->q($this->form->FormId));

				$this->db->setQuery($query)->execute();

				$this->form->FormId = $oldFormId;
			}
		}
		
		// Restore form translations
		if ($this->xml->structure->translations)
		{
			foreach ($this->xml->structure->translations->children() as $lang_code => $properties)
			{
				foreach ($properties->children() as $property => $value)
				{
					$data = array(
						'form_id' 		=> $this->form->FormId,
						'lang_code' 	=> (string) $lang_code,
						'reference' 	=> 'forms',
						'reference_id' 	=> (string) $property,
						'value' 		=> (string) $value
					);

					$data = (object) $data;

					$this->db->insertObject('#__rsform_translations', $data);
				}
			}
		}
	}
	
	// Fields
	// ======
	
	protected function restoreFields()
	{
		// Restore the form fields #__rsform_components
		if (isset($this->xml->fields))
		{
			foreach ($this->xml->fields->children() as $field)
			{
				$componentTypeId = (string) $field->ComponentTypeId;
				// change fieldType if needed
				$changedField = '';
				if ($componentTypeId == '12')
				{
					$componentTypeId = '13';
					$changedField = 'imageButton';
				}

				$data = array(
					'FormId'            => $this->form->FormId,
					'ComponentTypeId'   => $componentTypeId,
					'Order'             => (string) $field->Order,
					'Published'         => (string) $field->Published
				);

				$data = (object) $data;

				$this->db->insertObject('#__rsform_components', $data, 'ComponentId');

				$componentId = $data->ComponentId;
				
				// we use the switch statement for further field types changes - at the moment we only need it for the image button
				$referenceProperties = array();
				if (!empty($changedField))
				{
					switch ($changedField)
					{
						case 'imageButton':
							$query = $this->db->getQuery(true);
							$query->select($this->db->qn('FieldName'))
								->from($this->db->qn('#__rsform_component_type_fields'))
								->where($this->db->qn('ComponentTypeId') . ' = ' . $this->db->q(13));
							$this->db->setQuery($query);
							$referenceProperties = $this->db->loadColumn();
						break;
					}
				}

				if (isset($field->properties))
				{
					$newProperties = array();
					foreach ($field->properties->children() as $property => $value)
					{
						$property = (string) $property;
						$value = (string) $value;
						
						if (!isset($newProperties[$componentId]))
						{
							$newProperties[$componentId] = array();
						}
						
						if (!empty($changedField))
						{
							switch ($changedField)
							{
								case 'imageButton':
									if (in_array($property, $referenceProperties))
									{
										if ($property == 'ADDITIONALATTRIBUTES' && isset($newProperties[$componentId]['ADDITIONALATTRIBUTES']))
										{
											$newProperties[$componentId]['ADDITIONALATTRIBUTES'] = $value."\r\n".$newProperties[$componentId]['ADDITIONALATTRIBUTES'];	
										}
										else
										{
											$newProperties[$componentId][$property] = $value;
										}
									}
									elseif ($property == 'IMAGEBUTTON' && !empty($value))
									{
										$additional = 'type="image"'."\r\n".'src="'.$value.'"';
										if (isset($newProperties[$componentId]['ADDITIONALATTRIBUTES']) && !empty($newProperties[$componentId]['ADDITIONALATTRIBUTES']))
										{
											$additional = $newProperties[$componentId]['ADDITIONALATTRIBUTES']."\r\n".$additional;
										}
										$newProperties[$componentId]['ADDITIONALATTRIBUTES'] = $additional;
									}
								break;
							}
						}
						else
						{
							$newProperties[$componentId][$property] = $value;
						}
					}
					
					// add the submit button extra properties
					if (!empty($changedField))
					{
						switch ($changedField)
						{
							case 'imageButton':
								foreach ($newProperties as $CompId => $property)
								{
									foreach ($referenceProperties as $referenceProperty)
									{
										$value = '';

										switch ($referenceProperty)
										{
											case 'DISPLAYPROGRESS':
												$value = 'NO';
											break;
											case 'DISPLAYPROGRESSMSG':
												$value = '<div>'."\r\n".' <p><em>Page <strong>{page}</strong> of {total}</em></p>'."\r\n".' <div class="rsformProgressContainer">'."\r\n".'  <div class="rsformProgressBar" style="width: {percent}%;"></div>'."\r\n".' </div>'."\r\n".'</div>';
											break;
										}
										
										if (!empty($value))
										{
											$newProperties[$CompId][$referenceProperty] = $value;
										}
									}
								}
							break;
						}
					}

					foreach ($newProperties as $CompId => $property)
					{
						foreach ($property as $propertyName => $propertyValue)
						{
							$data = array(
								'ComponentId'   => $CompId,
								'PropertyName'  => $propertyName,
								'PropertyValue' => $propertyValue
							);

							$data = (object) $data;

							$this->db->insertObject('#__rsform_properties', $data);

							// store the ComponentId
							if ((string) $propertyName == 'NAME')
							{
								$this->fields[(string) $propertyValue] = $CompId;
							}
						}
					}
				}
				if (isset($field->translations))
				{
					foreach ($field->translations->children() as $lang_code => $properties)
					{
						foreach ($properties->children() as $property => $value)
						{
							$data = array(
								'form_id'       => $this->form->FormId,
								'lang_code'     => (string) $lang_code,
								'reference'     => 'properties',
								'reference_id'  => $componentId . '.' . (string) $property,
								'value'         => (string) $value
							);

							$data = (object) $data;

							$this->db->insertObject('#__rsform_translations', $data);
						}
					}
				}
			}
		}
	}
	
	protected function rebuildCalendarsValidationRules()
	{
		$db 	= &$this->db;
		$query 	= $db->getQuery(true);
		
		$query->clear()
			  ->select('c.ComponentId')
			  ->select('p.PropertyName')
			  ->select('p.PropertyValue')
			  ->from($db->qn('#__rsform_components', 'c'))
			  ->join('LEFT', $db->qn('#__rsform_properties', 'p') . ' ON (' . $db->qn('c.ComponentId') . ' = ' . $db->qn('p.ComponentId') . ')')
			  ->where($db->qn('c.FormId').' = '.$db->q($this->form->FormId))
			  ->where('('.$db->qn('p.PropertyName').' = '.$db->q('NAME').' OR '.$db->qn('p.PropertyName').' = '.$db->q('VALIDATIONCALENDAR').')');
		$db->setQuery($query);
		$formCalendarsComponents = $db->loadObjectList();
		
		$componentsNames = array();
		$componentsValidations = array();
		
		foreach ($formCalendarsComponents as $calendar)
		{
			if ($calendar->PropertyName == 'NAME')
			{
				$componentsNames[$calendar->PropertyValue] = $calendar->ComponentId;
			}
			
			if ($calendar->PropertyName == 'VALIDATIONCALENDAR')
			{
				$componentsValidations[$calendar->ComponentId] = $calendar->PropertyValue;
			}
		}
		
		foreach ($componentsValidations as $componentId => $value)
		{
			if (!empty($value))
			{
				$ruleParts = explode(' ', $value, 2);
				$otherComponentName = $ruleParts[1];
				
				$idOtherComponent = $componentsNames[$otherComponentName];
				$ruleParts[1] = $idOtherComponent; // replace the name with the id

				$data = array(
					'ComponentId'   => $componentId,
					'PropertyName'  => 'VALIDATIONCALENDAR',
					'PropertyValue' => implode(' ', $ruleParts)
				);

				$data = (object) $data;

				$this->db->updateObject('#__rsform_properties', $data, array('ComponentId', 'PropertyName'));
			}
		}
	}

	protected function rebuildPreviewSelectFields()
	{
		$db 	= &$this->db;
		$query 	= $db->getQuery(true);

		$query->clear()
			->select('c.ComponentId')
			->select('p.PropertyName')
			->select('p.PropertyValue')
			->from($db->qn('#__rsform_components', 'c'))
			->join('LEFT', $db->qn('#__rsform_properties', 'p') . ' ON (' . $db->qn('c.ComponentId') . ' = ' . $db->qn('p.ComponentId') . ')')
			->where($db->qn('c.FormId').' = '.$db->q($this->form->FormId))
			->where('('.$db->qn('p.PropertyName').' = '.$db->q('NAME').' OR '.$db->qn('p.PropertyName').' = '.$db->q('SELECTFIELD').')');
		$db->setQuery($query);
		$formComponents = $db->loadObjectList();

		$componentsNames = array();
		$componentsSelectFields = array();

		foreach ($formComponents as $formComponent)
		{
			if ($formComponent->PropertyName == 'NAME')
			{
				$componentsNames[$formComponent->PropertyValue] = $formComponent->ComponentId;
			}

			if ($formComponent->PropertyName == 'SELECTFIELD')
			{
				$componentsSelectFields[$formComponent->ComponentId] = $formComponent->PropertyValue;
			}
		}

		foreach ($componentsSelectFields as $componentId => $value)
		{
			if (!empty($value))
			{
				$idOtherComponent = $componentsNames[$value];

				$data = array(
					'ComponentId'   => $componentId,
					'PropertyName'  => 'SELECTFIELD',
					'PropertyValue' => $idOtherComponent
				);

				$data = (object) $data;

				$this->db->updateObject('#__rsform_properties', $data, array('ComponentId', 'PropertyName'));
			}
		}
	}
	
	// Calculations
	// ============
	
	protected function restoreCalculations()
	{
		// Restore Calculations #__rsform_calculations
		if (isset($this->xml->calculations))
		{
			foreach ($this->xml->calculations->children() as $calculation)
			{
				$data = array(
					'formId'        => $this->form->FormId,
					'total'         => (string) $calculation->total,
					'expression'    => (string) $calculation->expression,
					'ordering'      => (string) $calculation->ordering
				);

				$data = (object) $data;

				$this->db->insertObject('#__rsform_calculations', $data);
			}
		}
	}
	
	// Post
	// ====
	
	protected function restorePost()
	{
		// Restore Post to Location #__rsform_posts
		if (isset($this->xml->post))
		{
			foreach ($this->xml->post as $post)
			{
				// Some older versions might have left some data here due to a bug, must delete it first.
				$query = $this->db->getQuery(true);
				$query->delete('#__rsform_posts')
					  ->where($this->db->qn('form_id').' = '.$this->db->q($this->form->FormId));
				$this->db->setQuery($query)->execute();

				$data = array(
					'form_id'   => $this->form->FormId,
					'enabled'   => (string) $post->enabled,
					'method'    => (string) $post->method,
					'fields'    => (string) $post->fields,
					'headers'   => (string) $post->headers,
					'silent'    => (string) $post->silent,
					'url'       => (string) $post->url
				);

				$data = (object) $data;

				$this->db->insertObject('#__rsform_posts', $data);
			}
		}
	}
	
	// Conditions
	// ==========
	
	protected function restoreConditions()
	{
		// Restore conditions #__rsform_conditions & #__rsform_condition_details
		if (isset($this->xml->conditions))
		{
			require_once JPATH_ADMINISTRATOR . '/components/com_rsform/helpers/conditions.php';

			foreach ($this->xml->conditions->children() as $condition)
			{
				$component_ids = (string) $condition->component_id;

				$tmp_ids = json_decode($component_ids);
				if (is_array($tmp_ids))
				{
					$component_ids = $tmp_ids;
				}
				else
				{
					$component_ids = array($component_ids);
				}

				$json_ids = array();
				foreach ($component_ids as $component_id)
				{
					if (isset($this->fields[$component_id]))
					{
						$json_ids[] = $this->fields[$component_id];
					}
				}
				$json_ids = json_encode($json_ids);

				$data = array(
					'form_id'       => $this->form->FormId,
					'action'        => (string) $condition->action,
					'block'         => (string) $condition->block,
					'component_id'  => $json_ids,
					'condition'     => (string) $condition->condition,
					'lang_code'     => (string) $condition->lang_code,
				);

				$data = (object) $data;

				$this->db->insertObject('#__rsform_conditions', $data, 'id');

				$conditionId = $data->id;
				
				if (isset($condition->details))
				{
					foreach ($condition->details->children() as $detail)
					{
						if (!isset($this->fields[(string) $detail->component_id]))
						{
							continue;
						}

						$data = array(
							'condition_id'  => $conditionId,
							'component_id'  => $this->fields[(string) $detail->component_id],
							'operator'      => (string) $detail->operator,
							'value'         => (string) $detail->value
						);

						$data = (object) $data;

						$this->db->insertObject('#__rsform_condition_details', $data);
					}
				}
			}
		}
	}
	
	// Directory
	// =========
	
	protected function restoreDirectory()
	{
		// Restore directory #__rsform_directory & #__rsform_directory_fields
		if (isset($this->xml->directory))
		{
			foreach ($this->xml->directory as $directory)
			{
				$data = array(
					'formId'                    => $this->form->FormId,
					'filename'                  => (string) $directory->filename,
					'csvfilename'               => (string) $directory->csvfilename,
					'enablepdf'                 => (int) $directory->enablepdf,
					'enablecsv'                 => (int) $directory->enablecsv,
					'AllowCSVFullDownload'      => (int) $directory->AllowCSVFullDownload,
					'HideEmptyValues'           => (int) $directory->HideEmptyValues,
					'ShowGoogleMap'             => (int) $directory->ShowGoogleMap,
					'ViewLayout'                => (string) $directory->ViewLayout,
					'ViewLayoutName'            => (string) $directory->ViewLayoutName,
					'ViewLayoutAutogenerate'    => (int) $directory->ViewLayoutAutogenerate,
					'CSS'                       => (string) $directory->CSS,
					'JS'                        => (string) $directory->JS,
					'ListScript'                => (string) $directory->ListScript,
					'DetailsScript'             => (string) $directory->DetailsScript,
					'EditScript'                => (string) $directory->EditScript,
					'SaveScript'                => (string) $directory->SaveScript,
					'EmailsScript'              => (string) $directory->EmailsScript,
					'EmailsCreatedScript'       => (string) $directory->EmailsCreatedScript,
					'groups'                    => (string) $directory->groups,
					'DeletionGroups'            => (string) $directory->DeletionGroups
				);

				$data = (object) $data;

				$this->db->insertObject('#__rsform_directory', $data);
				
				if (isset($directory->fields))
				{
					foreach ($directory->fields->children() as $field)
					{
						// check for the component ID
						$componentId = (string) $field->componentId;
						
						if (isset($this->fields[$componentId]))
						{
							$componentId = $this->fields[$componentId];
						}
						
						$componentId = (int) $componentId;
						
						if (is_int($componentId) && $componentId !== 0)
						{
							$data = array(
								'formId'        => $this->form->FormId,
								'componentId'   => $componentId,
								'viewable'      => (int) $field->viewable,
								'searchable'    => (int) $field->searchable,
								'editable'      => (int) $field->editable,
								'indetails'     => (int) $field->indetails,
								'incsv'         => (int) $field->incsv,
								'sort'          => (int) $field->sort,
								'ordering'      => (int) $field->ordering,
							);

							$data = (object) $data;

							$this->db->insertObject('#__rsform_directory_fields', $data);
						}
					}
				}
			}
		}
	}
	
	// Emails
	// ======
	
	protected function restoreEmails()
	{
		// Restore Emails #__rsform_emails
		if (isset($this->xml->emails))
		{
			foreach ($this->xml->emails->children() as $email)
			{
				$data = array(
					'formId'        => $this->form->FormId,
					'type'          => (string) $email->type,
					'from'          => (string) $email->from,
					'fromname'      => (string) $email->fromname,
					'replyto'       => (string) $email->replyto,
					'replytoname'   => (string) $email->replytoname,
					'to'            => (string) $email->to,
					'cc'            => (string) $email->cc,
					'bcc'           => (string) $email->bcc,
					'subject'       => (string) $email->subject,
					'mode'          => (string) $email->mode,
					'message'       => (string) $email->message
				);

				$data = (object) $data;

				$this->db->insertObject('#__rsform_emails', $data, 'id');

				$emailId = $data->id;
				
				if (isset($email->translations))
				{
					foreach ($email->translations->children() as $lang_code => $properties)
					{
						foreach ($properties->children() as $property => $value)
						{
							$data = array(
								'form_id' 		=> $this->form->FormId,
								'lang_code' 	=> (string) $lang_code,
								'reference' 	=> 'emails',
								'reference_id' 	=> $emailId . '.' . (string) $property,
								'value' 		=> (string) $value
							);

							$data = (object) $data;

							$this->db->insertObject('#__rsform_translations', $data);
						}
					}
				}
			}
		}
	}
	
	// Mappings
	// ========
	
	protected function restoreMappings()
	{
		// Restore Mappings #__rsform_mappings
		if (isset($this->xml->mappings))
		{
			$defaultDriver 	= Factory::getApplication()->get('dbtype');
			$prefix			= Factory::getApplication()->get('dbprefix');

			foreach ($this->xml->mappings->children() as $mapping)
			{
				$driver = (string) $mapping->driver;
				if (empty($driver))
				{
					$driver = $defaultDriver;
				}

				$table = (string) $mapping->table;
				if (strpos($table, '#__') === 0)
				{
					$table = substr_replace($table, $prefix, 0, strlen('#__'));
				}

				$data = array(
					'formId'        => $this->form->FormId,
					'connection'    => (string) $mapping->connection,
					'host'          => (string) $mapping->host,
					'port'          => (string) $mapping->port,
					'driver'        => $driver,
					'username'      => (string) $mapping->username,
					'password'      => (string) $mapping->password,
					'database'      => (string) $mapping->database,
					'method'        => (string) $mapping->method,
					'table'         => $table,
					'data'          => (string) $mapping->data,
					'wheredata'     => (string) $mapping->wheredata,
					'extra'         => (string) $mapping->extra,
					'andor'         => (string) $mapping->andor,
					'ordering'      => (string) $mapping->ordering
				);

				$data = (object) $data;

				$this->db->insertObject('#__rsform_mappings', $data);
			}
		}
	}

	// Grid Layout
    // ===========

	protected function rebuildGridLayout()
    {
        if (empty($this->form->GridLayout))
        {
            return false;
        }

        $data   = json_decode($this->form->GridLayout, true);
        $rows 	= array();
        $hidden	= array();

        // If decoding is successful, we should have $rows and $hidden
        if (is_array($data) && isset($data[0], $data[1]))
        {
            $rows 	= $data[0];
            $hidden = $data[1];
        }

        if ($rows)
        {
            foreach ($rows as $row_index => &$row)
            {
                foreach ($row['columns'] as $column_index => $fields)
                {
                    foreach ($fields as $position => $id)
                    {
                        if (isset($this->fields[$id]))
                        {
                            $row['columns'][$column_index][$position] = $this->fields[$id];
                        }
                        else
                        {
                            // Field doesn't exist, remove it from grid
                            unset($row['columns'][$column_index][$position]);
                        }
                    }
                }
            }
			unset($row);
        }

        if ($hidden)
        {
            foreach ($hidden as $hidden_index => $id)
            {
                if (isset($this->fields[$id]))
                {
                    $hidden[$hidden_index] = $this->fields[$id];
                }
                else
                {
                    // Field doesn't exist, remove it from grid
                    unset($hidden[$hidden_index]);
                }
            }
        }

        $data = array(
        	'FormId'        => $this->form->FormId,
	        'GridLayout'    => json_encode(array($rows, $hidden))
        );

        $data = (object) $data;

        $this->db->updateObject('#__rsform_forms', $data, array('FormId'));
    }
}

© 2025 Cubjrnet7