<commit_before><?php

/**
 * Helper file for handing themes.
 *
 * Simple Machines Forum (SMF)
 *
 * @package SMF
 * @author Simple Machines
 *
 * @copyright 2013 Simple Machines and individual contributors
 * @license http://www.simplemachines.org/about/smf/license.php BSD
 *
 * @version 2.1 Alpha 1
 */

if (!defined('SMF'))
	die('No direct access...');

function get_single_theme($id)
{
	global $smcFunc, $modSettings;

	// No data, no fun!
	if (empty($id))
		return false;

	// List of all possible  values.
	$themeValues = array(
		'theme_dir',
		'images_url',
		'theme_url',
		'name',
		'theme_layers',
		'theme_templates',
		'version',
		'install_for',
		'based_on',
	);

	$single = array(
		'id' => (int) $id,
	);

	// Make our known/enable themes a little easier to work with.
	$knownThemes = !empty($modSettings['knownThemes']) ? explode(',',$modSettings['knownThemes']) : array();
	$enableThemes = !empty($modSettings['enableThemes']) ? explode(',',$modSettings['enableThemes']) : array();

	$request = $smcFunc['db_query']('', '
		SELECT id_theme, variable, value
		FROM {db_prefix}themes
		WHERE variable IN ({array_string:theme_values})
			AND id_theme = ({int:id_theme})
			AND id_member = {int:no_member}',
		array(
			'theme_values' => $themeValues,
			'id_theme' => $id,
			'no_member' => 0,
		)
	);

	while ($row = $smcFunc['db_fetch_assoc']($request))
		$single[$row['variable']] = $row['value'];

	// Fix the path and tell if its a valid one.
	$single['theme_dir'] = realpath($single['theme_dir']);
	$single['valid_path'] = file_exists($single['theme_dir']) && is_dir($single['theme_dir']);
	$single['known'] = in_array($single['id'], $knownThemes);
	$single['enable'] = in_array($single['id'], $enableThemes);

	return $single;
}

function get_all_themes($enable_only = false)
{
	global $modSettings, $context, $smcFunc;

	// Make our known/enable themes a little easier to work with.
	$knownThemes = !empty($modSettings['knownThemes']) ? explode(',',$modSettings['knownThemes']) : array();
	$enableThemes = !empty($modSettings['enableThemes']) ? explode(',',$modSettings['enableThemes']) : array();

	// List of all possible themes values.
	$themeValues = array(
		'theme_dir',
		'images_url',
		'theme_url',
		'name',
		'theme_layers',
		'theme_templates',
		'version',
		'install_for',
		'based_on',
	);

	// So, what is it going to be?
	$query_where = $enable_only ? $enableThemes : $knownThemes;

	// Perform the query as requested.
	$request = $smcFunc['db_query']('', '
		SELECT id_theme, variable, value
		FROM {db_prefix}themes
		WHERE variable IN ({array_string:theme_values})
			AND id_theme IN ({array_string:query_where})
			AND id_member = {int:no_member}',
		array(
			'query_where' => $query_where,
			'theme_values' => $themeValues,
			'no_member' => 0,
		)
	);

	$context['themes'] = array();

	while ($row = $smcFunc['db_fetch_assoc']($request))
	{
		$context['themes'][$row['id_theme']]['id'] = (int) $row['id_theme'];

		// Fix the path and tell if its a valid one.
		if ($row['variable'] == 'theme_dir')
		{
			$context['themes'][$row['id_theme']][$row['variable']] = realpath($row['value']);
			$context['themes'][$row['id_theme']]['valid_path'] = file_exists(realpath($row['value'])) && is_dir(realpath($row['value']));
		}

		$context['themes'][$row['id_theme']]['known'] = in_array($row['id_theme'], $knownThemes);
		$context['themes'][$row['id_theme']]['enable'] = in_array($row['id_theme'], $enableThemes);
		$context['themes'][$row['id_theme']][$row['variable']] = $row['value'];
	}

	$smcFunc['db_free_result']($request);

	return $context['themes'];
}

function get_theme_info($path)
{
	global $sourcedir, $forum_version, $txt, $scripturl, $context;
	global $explicit_images;

	if (empty($path))
		return false;

	$xml_data = array();
	$explicit_images = false;

	// Perhaps they are trying to install a mod, lets tell them nicely this is the wrong function.
	if (file_exists($path . '/package-info.xml'))
	{
		loadLanguage('Errors');

		// We need to delete the dir otherwise the next time you try to install a theme you will get the same error.
		remove_dir($path);

		$txt['package_get_error_is_mod'] = str_replace('{MANAGEMODURL}', $scripturl . '?action=admin;area=packages;' . $context['session_var'] . '=' . $context['session_id'], $txt['package_get_error_is_mod']);
		fatal_lang_error('package_theme_upload_error_broken', false, $txt['package_get_error_is_mod']);
	}

	// Parse theme-info.xml into an xmlArray.
	require_once($sourcedir . '/Class-Package.php');
	$theme_info_xml = new xmlArray(file_get_contents($path . '/theme_info.xml'));

	// Error message, there isn't any valid info.
	if (!$theme_info_xml->exists('theme-info[0]'))
	{
		remove_dir($path);
		fatal_lang_error('package_get_error_packageinfo_corrupt', false);
	}

	// Check for compatibility with 2.1 or greater.
	if (!$theme_info_xml->exists('theme-info/install'))
	{
		remove_dir($path);
		fatal_lang_error('package_get_error_theme_not_compatible', false, $forum_version);
	}

	// So, we have an install tag which is cool and stuff but we also need to check it and match your current SMF version...
	$the_version = strtr($forum_version, array('SMF ' => ''));
	$install_versions = $theme_info_xml->path('theme-info/install/@for');

	// The theme isn't compatible with the current SMF version.
	if (!$install_versions || !matchPackageVersion($the_version, $install_versions))
	{
		remove_dir($path);
		fatal_lang_error('package_get_error_theme_not_compatible', false, $forum_version);
	}

	$theme_info_xml = $theme_info_xml->path('theme-info[0]');
	$theme_info_xml = $theme_info_xml->to_array();

	$xml_elements = array(
		'theme_layers' => 'layers',
		'theme_templates' => 'templates',
		'based_on' => 'based-on',
		'version' => 'version',
	);

	// Assign the values to be stored.
	foreach ($xml_elements as $var => $name)
		if (!empty($theme_info_xml[$name]))
			$xml_data[$var] = $theme_info_xml[$name];

	// Add the supported versions.
	$xml_data['install_for'] = $install_versions;

	// Overwrite the default images folder.
	if (!empty($theme_info_xml['images']))
	{
		$xml_data['images_url'] = $path . '/' . $theme_info_xml['images'];
		$explicit_images = true;
	}

	if (!empty($theme_info_xml['extra']))
		$xml_data += unserialize($theme_info_xml['extra']);

	return $xml_data;
}

function theme_install($to_install = array())
{
	global $smcFunc, $context, $themedir, $themeurl, $modSettings;
	global $settings, $explicit_images;

	// External use? no problem!
	if ($to_install)
		$context['to_install'] = $to_install;

	// One last check.
	if (empty($context['to_install']['theme_dir']) || basename($context['to_install']['theme_dir']) == 'Themes')
		fatal_lang_error('theme_install_invalid_dir', false);

	// OK, is this a newer version of an already installed theme?
	if (!empty($context['to_install']['version']))
	{
		$to_update = array();
		$request = $smcFunc['db_query']('', '
			SELECT id_theme, variable, value
			FROM {db_prefix}themes
			WHERE id_member = {int:no_member}
				AND id_member = {int:no_member}
				AND variable = {string:name}
				AND value LIKE {string:name_value}
			LIMIT 1',
			array(
				'no_member' => 0,
				'name' => 'name',
				'version' => 'version',
				'name_value' => '%'. $context['to_install']['name'] .'%',
			)
		);

		$to_update = $smcFunc['db_fetch_assoc']($request);
		$smcFunc['db_free_result']($request);

		// Got something, lets figure it out what to do next.
		if (!empty($to_update) && !empty($to_update['version']))
			switch (compareVersions($context['to_install']['version'], $to_update['version']))
			{
				case 0: // This is exactly the same theme.
				case -1: // The one being installed is older than the one already installed.
				default: // Any other possible result.
					fatal_lang_error('package_get_error_theme_no_new_version', false, array($context['to_install']['version'], $to_update['version']));
					break;
				case 1: // Got a newer version, update the old entry.
					$smcFunc['db_query']('', '
						UPDATE {db_prefix}themes
						SET value = {string:new_value}
						WHERE variable = {string:version}
							AND id_theme = {int:id_theme}',
						array(
							'new_value' => $context['to_install']['version'],
							'version' => 'version',
							'id_theme' => $to_update['id_theme'],
						)
					);

					// Done with the update, tell the user about it.
					$context['to_install']['updated'] = true;
					$context['to_install']['id'] = $to_update['id_theme'];

					return $context['to_install'];
					break; // Just for reference.
			}
	}

	if (!empty($context['to_install']['based_on']))
	{
		// No need for elaborated stuff when the theme is based on the default one.
		if ($context['to_install']['based_on'] == 'default')
		{
			$context['to_install']['theme_url'] = $settings['default_theme_url'];
			$context['to_install']['images_url'] = $settings['default_images_url'];
		}

		// Custom theme based on another custom theme, lets get some info.
		elseif ($context['to_install']['based_on'] != '')
		{
			$context['to_install']['based_on'] = preg_replace('~[^A-Za-z0-9\-_ ]~', '', $context['to_install']['based_on']);

			// Get the theme info first.
			$request = $smcFunc['db_query']('', '
				SELECT id_theme
				FROM {db_prefix}themes
				WHERE th.id_member = {int:no_member}
					AND (value LIKE {string:based_on} OR value LIKE {string:based_on_path})
					AND variable = {string:theme_dir}
				LIMIT 1',
				array(
					'no_member' => 0,
					'based_on' => '%/' . $context['to_install']['based_on'],
					'based_on_path' => '%' . "\\" . $context['to_install']['based_on'],
				)
			);

			$based_on = $smcFunc['db_fetch_assoc']($request);
			$smcFunc['db_free_result']($request);

			$request = $smcFunc['db_query']('', '
				SELECT variable, value
				FROM {db_prefix}themes
					WHERE variable IN ({array_string:theme_values})
						AND id_theme = ({int:based_on})
				LIMIT 1',
				array(
					'no_member' => 0,
					'theme__values' => array('theme_url', 'images_url', 'theme_dir',),
					'based_on' => $based_on,
				)
			);
			$temp = $smcFunc['db_fetch_assoc']($request);
			$smcFunc['db_free_result']($request);

			// Found the based on theme info, add it to the current one being installed.
			if (is_array($temp))
			{
				$context['to_install'] = $temp + $context['to_install'];

				if (empty($explicit_images) && !empty($context['to_install']['base_theme_url']))
					$context['to_install']['theme_url'] = $context['to_install']['base_theme_url'];
			}

			// Nope, sorry, couldn't find any theme already installed.
			else
				fatal_lang_error('package_get_error_theme_no_based_on_found', false, $context['to_install']['based_on']);
		}

		unset($context['to_install']['based_on']);
	}
<commit_msg>Fix based_on vars<commit_after><?php

/**
 * Helper file for handing themes.
 *
 * Simple Machines Forum (SMF)
 *
 * @package SMF
 * @author Simple Machines
 *
 * @copyright 2013 Simple Machines and individual contributors
 * @license http://www.simplemachines.org/about/smf/license.php BSD
 *
 * @version 2.1 Alpha 1
 */

if (!defined('SMF'))
	die('No direct access...');

function get_single_theme($id)
{
	global $smcFunc, $modSettings;

	// No data, no fun!
	if (empty($id))
		return false;

	// List of all possible  values.
	$themeValues = array(
		'theme_dir',
		'images_url',
		'theme_url',
		'name',
		'theme_layers',
		'theme_templates',
		'version',
		'install_for',
		'based_on',
	);

	$single = array(
		'id' => (int) $id,
	);

	// Make our known/enable themes a little easier to work with.
	$knownThemes = !empty($modSettings['knownThemes']) ? explode(',',$modSettings['knownThemes']) : array();
	$enableThemes = !empty($modSettings['enableThemes']) ? explode(',',$modSettings['enableThemes']) : array();

	$request = $smcFunc['db_query']('', '
		SELECT id_theme, variable, value
		FROM {db_prefix}themes
		WHERE variable IN ({array_string:theme_values})
			AND id_theme = ({int:id_theme})
			AND id_member = {int:no_member}',
		array(
			'theme_values' => $themeValues,
			'id_theme' => $id,
			'no_member' => 0,
		)
	);

	while ($row = $smcFunc['db_fetch_assoc']($request))
		$single[$row['variable']] = $row['value'];

	// Fix the path and tell if its a valid one.
	$single['theme_dir'] = realpath($single['theme_dir']);
	$single['valid_path'] = file_exists($single['theme_dir']) && is_dir($single['theme_dir']);
	$single['known'] = in_array($single['id'], $knownThemes);
	$single['enable'] = in_array($single['id'], $enableThemes);

	return $single;
}

function get_all_themes($enable_only = false)
{
	global $modSettings, $context, $smcFunc;

	// Make our known/enable themes a little easier to work with.
	$knownThemes = !empty($modSettings['knownThemes']) ? explode(',',$modSettings['knownThemes']) : array();
	$enableThemes = !empty($modSettings['enableThemes']) ? explode(',',$modSettings['enableThemes']) : array();

	// List of all possible themes values.
	$themeValues = array(
		'theme_dir',
		'images_url',
		'theme_url',
		'name',
		'theme_layers',
		'theme_templates',
		'version',
		'install_for',
		'based_on',
	);

	// So, what is it going to be?
	$query_where = $enable_only ? $enableThemes : $knownThemes;

	// Perform the query as requested.
	$request = $smcFunc['db_query']('', '
		SELECT id_theme, variable, value
		FROM {db_prefix}themes
		WHERE variable IN ({array_string:theme_values})
			AND id_theme IN ({array_string:query_where})
			AND id_member = {int:no_member}',
		array(
			'query_where' => $query_where,
			'theme_values' => $themeValues,
			'no_member' => 0,
		)
	);

	$context['themes'] = array();

	while ($row = $smcFunc['db_fetch_assoc']($request))
	{
		$context['themes'][$row['id_theme']]['id'] = (int) $row['id_theme'];

		// Fix the path and tell if its a valid one.
		if ($row['variable'] == 'theme_dir')
		{
			$context['themes'][$row['id_theme']][$row['variable']] = realpath($row['value']);
			$context['themes'][$row['id_theme']]['valid_path'] = file_exists(realpath($row['value'])) && is_dir(realpath($row['value']));
		}

		$context['themes'][$row['id_theme']]['known'] = in_array($row['id_theme'], $knownThemes);
		$context['themes'][$row['id_theme']]['enable'] = in_array($row['id_theme'], $enableThemes);
		$context['themes'][$row['id_theme']][$row['variable']] = $row['value'];
	}

	$smcFunc['db_free_result']($request);

	return $context['themes'];
}

function get_theme_info($path)
{
	global $sourcedir, $forum_version, $txt, $scripturl, $context;
	global $explicit_images;

	if (empty($path))
		return false;

	$xml_data = array();
	$explicit_images = false;

	// Perhaps they are trying to install a mod, lets tell them nicely this is the wrong function.
	if (file_exists($path . '/package-info.xml'))
	{
		loadLanguage('Errors');

		// We need to delete the dir otherwise the next time you try to install a theme you will get the same error.
		remove_dir($path);

		$txt['package_get_error_is_mod'] = str_replace('{MANAGEMODURL}', $scripturl . '?action=admin;area=packages;' . $context['session_var'] . '=' . $context['session_id'], $txt['package_get_error_is_mod']);
		fatal_lang_error('package_theme_upload_error_broken', false, $txt['package_get_error_is_mod']);
	}

	// Parse theme-info.xml into an xmlArray.
	require_once($sourcedir . '/Class-Package.php');
	$theme_info_xml = new xmlArray(file_get_contents($path . '/theme_info.xml'));

	// Error message, there isn't any valid info.
	if (!$theme_info_xml->exists('theme-info[0]'))
	{
		remove_dir($path);
		fatal_lang_error('package_get_error_packageinfo_corrupt', false);
	}

	// Check for compatibility with 2.1 or greater.
	if (!$theme_info_xml->exists('theme-info/install'))
	{
		remove_dir($path);
		fatal_lang_error('package_get_error_theme_not_compatible', false, $forum_version);
	}

	// So, we have an install tag which is cool and stuff but we also need to check it and match your current SMF version...
	$the_version = strtr($forum_version, array('SMF ' => ''));
	$install_versions = $theme_info_xml->path('theme-info/install/@for');

	// The theme isn't compatible with the current SMF version.
	if (!$install_versions || !matchPackageVersion($the_version, $install_versions))
	{
		remove_dir($path);
		fatal_lang_error('package_get_error_theme_not_compatible', false, $forum_version);
	}

	$theme_info_xml = $theme_info_xml->path('theme-info[0]');
	$theme_info_xml = $theme_info_xml->to_array();

	$xml_elements = array(
		'theme_layers' => 'layers',
		'theme_templates' => 'templates',
		'based_on' => 'based-on',
		'version' => 'version',
	);

	// Assign the values to be stored.
	foreach ($xml_elements as $var => $name)
		if (!empty($theme_info_xml[$name]))
			$xml_data[$var] = $theme_info_xml[$name];

	// Add the supported versions.
	$xml_data['install_for'] = $install_versions;

	// Overwrite the default images folder.
	if (!empty($theme_info_xml['images']))
	{
		$xml_data['images_url'] = $path . '/' . $theme_info_xml['images'];
		$explicit_images = true;
	}

	if (!empty($theme_info_xml['extra']))
		$xml_data += unserialize($theme_info_xml['extra']);

	return $xml_data;
}

function theme_install($to_install = array())
{
	global $smcFunc, $context, $themedir, $themeurl, $modSettings;
	global $settings, $explicit_images;

	// External use? no problem!
	if ($to_install)
		$context['to_install'] = $to_install;

	// One last check.
	if (empty($context['to_install']['theme_dir']) || basename($context['to_install']['theme_dir']) == 'Themes')
		fatal_lang_error('theme_install_invalid_dir', false);

	// OK, is this a newer version of an already installed theme?
	if (!empty($context['to_install']['version']))
	{
		$to_update = array();
		$request = $smcFunc['db_query']('', '
			SELECT id_theme, variable, value
			FROM {db_prefix}themes
			WHERE id_member = {int:no_member}
				AND id_member = {int:no_member}
				AND variable = {string:name}
				AND value LIKE {string:name_value}
			LIMIT 1',
			array(
				'no_member' => 0,
				'name' => 'name',
				'version' => 'version',
				'name_value' => '%'. $context['to_install']['name'] .'%',
			)
		);

		$to_update = $smcFunc['db_fetch_assoc']($request);
		$smcFunc['db_free_result']($request);

		// Got something, lets figure it out what to do next.
		if (!empty($to_update) && !empty($to_update['version']))
			switch (compareVersions($context['to_install']['version'], $to_update['version']))
			{
				case 0: // This is exactly the same theme.
				case -1: // The one being installed is older than the one already installed.
				default: // Any other possible result.
					fatal_lang_error('package_get_error_theme_no_new_version', false, array($context['to_install']['version'], $to_update['version']));
					break;
				case 1: // Got a newer version, update the old entry.
					$smcFunc['db_query']('', '
						UPDATE {db_prefix}themes
						SET value = {string:new_value}
						WHERE variable = {string:version}
							AND id_theme = {int:id_theme}',
						array(
							'new_value' => $context['to_install']['version'],
							'version' => 'version',
							'id_theme' => $to_update['id_theme'],
						)
					);

					// Done with the update, tell the user about it.
					$context['to_install']['updated'] = true;
					$context['to_install']['id'] = $to_update['id_theme'];

					return $context['to_install'];
					break; // Just for reference.
			}
	}

	if (!empty($context['to_install']['based_on']))
	{
		// No need for elaborated stuff when the theme is based on the default one.
		if ($context['to_install']['based_on'] == 'default')
		{
			$context['to_install']['theme_url'] = $settings['default_theme_url'];
			$context['to_install']['images_url'] = $settings['default_images_url'];
		}

		// Custom theme based on another custom theme, lets get some info.
		elseif ($context['to_install']['based_on'] != '')
		{
			$context['to_install']['based_on'] = preg_replace('~[^A-Za-z0-9\-_ ]~', '', $context['to_install']['based_on']);

			// Get the theme info first.
			$request = $smcFunc['db_query']('', '
				SELECT id_theme
				FROM {db_prefix}themes
				WHERE th.id_member = {int:no_member}
					AND (value LIKE {string:based_on} OR value LIKE {string:based_on_path})
					AND variable = {string:theme_dir}
				LIMIT 1',
				array(
					'no_member' => 0,
					'based_on' => '%/' . $context['to_install']['based_on'],
					'based_on_path' => '%' . "\\" . $context['to_install']['based_on'],
				)
			);

			$based_on = $smcFunc['db_fetch_assoc']($request);
			$smcFunc['db_free_result']($request);

			$request = $smcFunc['db_query']('', '
				SELECT variable, value
				FROM {db_prefix}themes
					WHERE variable IN ({array_string:theme_values})
						AND id_theme = ({int:based_on})
				LIMIT 1',
				array(
					'no_member' => 0,
					'theme__values' => array('theme_url', 'images_url', 'theme_dir',),
					'based_on' => $based_on,
				)
			);
			$temp = $smcFunc['db_fetch_assoc']($request);
			$smcFunc['db_free_result']($request);

			// Found the based on theme info, add it to the current one being installed.
			if (is_array($temp))
			{
				$context['to_install']['base_theme_url'] = $temp['theme_url'];
				$context['to_install']['base_theme_dir'] = $temp['theme_dir'];

				if (empty($explicit_images) && !empty($context['to_install']['base_theme_url']))
					$context['to_install']['theme_url'] = $context['to_install']['base_theme_url'];
			}

			// Nope, sorry, couldn't find any theme already installed.
			else
				fatal_lang_error('package_get_error_theme_no_based_on_found', false, $context['to_install']['based_on']);
		}

		unset($context['to_install']['based_on']);
	}

{'fraction_non_alphanumeric': 0.18145554060949023, 'fraction_numerical': 0.00222644835103669, 'mean_word_length': 4.709745762711864, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 65, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 54}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1423498', 'n_tokens_mistral': 8298, 'n_tokens_neox': 7428, 'n_words': 1567}