diff options
Diffstat (limited to 'engine/lib/input.php')
| -rw-r--r-- | engine/lib/input.php | 520 | 
1 files changed, 520 insertions, 0 deletions
| diff --git a/engine/lib/input.php b/engine/lib/input.php new file mode 100644 index 000000000..80b0b8766 --- /dev/null +++ b/engine/lib/input.php @@ -0,0 +1,520 @@ +<?php +/** + * Parameter input functions. + * This file contains functions for getting input from get/post variables. + * + * @package Elgg.Core + * @subpackage Input + */ + +/** + * Get some input from variables passed submitted through GET or POST. + * + * If using any data obtained from get_input() in a web page, please be aware that + * it is a possible vector for a reflected XSS attack. If you are expecting an + * integer, cast it to an int. If it is a string, escape quotes. + * + * Note: this function does not handle nested arrays (ex: form input of param[m][n]) + * because of the filtering done in htmlawed from the filter_tags call. + * @todo Is this ^ still true? + * + * @param string $variable      The variable name we want. + * @param mixed  $default       A default value for the variable if it is not found. + * @param bool   $filter_result If true, then the result is filtered for bad tags. + * + * @return mixed + */ +function get_input($variable, $default = NULL, $filter_result = TRUE) { + +	global $CONFIG; + +	$result = $default; + +	elgg_push_context('input'); + +	if (isset($CONFIG->input[$variable])) { +		$result = $CONFIG->input[$variable]; + +		if ($filter_result) { +			$result = filter_tags($result); +		} +	} elseif (isset($_REQUEST[$variable])) { +		if (is_array($_REQUEST[$variable])) { +			$result = $_REQUEST[$variable]; +		} else { +			$result = trim($_REQUEST[$variable]); +		} + +		if ($filter_result) { +			$result = filter_tags($result); +		} +	} + +	elgg_pop_context(); + +	return $result; +} + +/** + * Sets an input value that may later be retrieved by get_input + * + * Note: this function does not handle nested arrays (ex: form input of param[m][n]) + * + * @param string          $variable The name of the variable + * @param string|string[] $value    The value of the variable + * + * @return void + */ +function set_input($variable, $value) { +	global $CONFIG; +	if (!isset($CONFIG->input)) { +		$CONFIG->input = array(); +	} + +	if (is_array($value)) { +		array_walk_recursive($value, create_function('&$v, $k', '$v = trim($v);')); +		$CONFIG->input[trim($variable)] = $value; +	} else { +		$CONFIG->input[trim($variable)] = trim($value); +	} +} + +/** + * Filter tags from a given string based on registered hooks. + * + * @param mixed $var Anything that does not include an object (strings, ints, arrays) + *					 This includes multi-dimensional arrays. + * + * @return mixed The filtered result - everything will be strings + */ +function filter_tags($var) { +	return elgg_trigger_plugin_hook('validate', 'input', null, $var); +} + +/** + * Validates an email address. + * + * @param string $address Email address. + * + * @return bool + */ +function is_email_address($address) { +	return filter_var($address, FILTER_VALIDATE_EMAIL) === $address; +} + +/** + * Load all the REQUEST variables into the sticky form cache + * + * Call this from an action when you want all your submitted variables + * available if the submission fails validation and is sent back to the form + * + * @param string $form_name Name of the sticky form + * + * @return void + * @link http://docs.elgg.org/Tutorials/UI/StickyForms + * @since 1.8.0 + */ +function elgg_make_sticky_form($form_name) { + +	elgg_clear_sticky_form($form_name); + +	if (!isset($_SESSION['sticky_forms'])) { +		$_SESSION['sticky_forms'] = array(); +	} +	$_SESSION['sticky_forms'][$form_name] = array(); + +	foreach ($_REQUEST as $key => $var) { +		// will go through XSS filtering on the get function +		$_SESSION['sticky_forms'][$form_name][$key] = $var; +	} +} + +/** + * Clear the sticky form cache + * + * Call this if validation is successful in the action handler or + * when they sticky values have been used to repopulate the form + * after a validation error. + * + * @param string $form_name Form namespace + * + * @return void + * @link http://docs.elgg.org/Tutorials/UI/StickyForms + * @since 1.8.0 + */ +function elgg_clear_sticky_form($form_name) { +	unset($_SESSION['sticky_forms'][$form_name]); +} + +/** + * Has this form been made sticky? + * + * @param string $form_name Form namespace + * + * @return boolean + * @link http://docs.elgg.org/Tutorials/UI/StickyForms + * @since 1.8.0 + */ +function elgg_is_sticky_form($form_name) { +	return isset($_SESSION['sticky_forms'][$form_name]); +} + +/** + * Get a specific sticky variable + * + * @param string  $form_name     The name of the form + * @param string  $variable      The name of the variable + * @param mixed   $default       Default value if the variable does not exist in sticky cache + * @param boolean $filter_result Filter for bad input if true + * + * @return mixed + * + * @todo should this filter the default value? + * @link http://docs.elgg.org/Tutorials/UI/StickyForms + * @since 1.8.0 + */ +function elgg_get_sticky_value($form_name, $variable = '', $default = NULL, $filter_result = true) { +	if (isset($_SESSION['sticky_forms'][$form_name][$variable])) { +		$value = $_SESSION['sticky_forms'][$form_name][$variable]; +		if ($filter_result) { +			// XSS filter result +			$value = filter_tags($value); +		} +		return $value; +	} +	return $default; +} + +/** + * Get all the values in a sticky form in an array + * + * @param string $form_name     The name of the form + * @param bool   $filter_result Filter for bad input if true + * + * @return array + * @since 1.8.0 + */ +function elgg_get_sticky_values($form_name, $filter_result = true) { +	if (!isset($_SESSION['sticky_forms'][$form_name])) { +		return array(); +	} + +	$values = $_SESSION['sticky_forms'][$form_name]; +	if ($filter_result) { +		foreach ($values as $key => $value) { +			// XSS filter result +			$values[$key] = filter_tags($value); +		} +	} +	return $values; +} + +/** + * Clear a specific sticky variable + * + * @param string $form_name The name of the form + * @param string $variable  The name of the variable to clear + * + * @return void + * @link http://docs.elgg.org/Tutorials/UI/StickyForms + * @since 1.8.0 + */ +function elgg_clear_sticky_value($form_name, $variable) { +	unset($_SESSION['sticky_forms'][$form_name][$variable]); +} + +/** + * Page handler for autocomplete endpoint. + * + * @todo split this into functions/objects, this is way too big + * + * /livesearch?q=<query> + * + * Other options include: + *     match_on	   string all or array(groups|users|friends) + *     match_owner int    0/1 + *     limit       int    default is 10 + * + * @param array $page + * @return string JSON string is returned and then exit + * @access private + */ +function input_livesearch_page_handler($page) { +	global $CONFIG; + +	// only return results to logged in users. +	if (!$user = elgg_get_logged_in_user_entity()) { +		exit; +	} + +	if (!$q = get_input('term', get_input('q'))) { +		exit; +	} + +	$q = sanitise_string($q); + +	// replace mysql vars with escaped strings +	$q = str_replace(array('_', '%'), array('\_', '\%'), $q); + +	$match_on = get_input('match_on', 'all'); + +	if (!is_array($match_on)) { +		$match_on = array($match_on); +	} + +	// all = users and groups +	if (in_array('all', $match_on)) { +		$match_on = array('users', 'groups'); +	} + +	if (get_input('match_owner', false)) { +		$owner_where = 'AND e.owner_guid = ' . $user->getGUID(); +	} else { +		$owner_where = ''; +	} + +	$limit = sanitise_int(get_input('limit', 10)); + +	// grab a list of entities and send them in json. +	$results = array(); +	foreach ($match_on as $match_type) { +		switch ($match_type) { +			case 'users': +				$query = "SELECT * FROM {$CONFIG->dbprefix}users_entity as ue, {$CONFIG->dbprefix}entities as e +					WHERE e.guid = ue.guid +						AND e.enabled = 'yes' +						AND ue.banned = 'no' +						AND (ue.name LIKE '$q%' OR ue.name LIKE '% $q%' OR ue.username LIKE '$q%') +					LIMIT $limit +				"; + +				if ($entities = get_data($query)) { +					foreach ($entities as $entity) { +						// @todo use elgg_get_entities (don't query in a loop!) +						$entity = get_entity($entity->guid); +						/* @var ElggUser $entity */ +						if (!$entity) { +							continue; +						} + +						if (in_array('groups', $match_on)) { +							$value = $entity->guid; +						} else { +							$value = $entity->username; +						} + +						$output = elgg_view_list_item($entity, array( +							'use_hover' => false, +							'class' => 'elgg-autocomplete-item', +						)); + +						$icon = elgg_view_entity_icon($entity, 'tiny', array( +							'use_hover' => false, +						)); + +						$result = array( +							'type' => 'user', +							'name' => $entity->name, +							'desc' => $entity->username, +							'guid' => $entity->guid, +							'label' => $output, +							'value' => $value, +							'icon' => $icon, +							'url' => $entity->getURL(), +						); +						$results[$entity->name . rand(1, 100)] = $result; +					} +				} +				break; + +			case 'groups': +				// don't return results if groups aren't enabled. +				if (!elgg_is_active_plugin('groups')) { +					continue; +				} +				$query = "SELECT * FROM {$CONFIG->dbprefix}groups_entity as ge, {$CONFIG->dbprefix}entities as e +					WHERE e.guid = ge.guid +						AND e.enabled = 'yes' +						$owner_where +						AND (ge.name LIKE '$q%' OR ge.name LIKE '% $q%' OR ge.description LIKE '% $q%') +					LIMIT $limit +				"; +				if ($entities = get_data($query)) { +					foreach ($entities as $entity) { +						// @todo use elgg_get_entities (don't query in a loop!) +						$entity = get_entity($entity->guid); +						/* @var ElggGroup $entity */ +						if (!$entity) { +							continue; +						} + +						$output = elgg_view_list_item($entity, array( +							'use_hover' => false, +							'class' => 'elgg-autocomplete-item', +						)); + +						$icon = elgg_view_entity_icon($entity, 'tiny', array( +							'use_hover' => false, +						)); + +						$result = array( +							'type' => 'group', +							'name' => $entity->name, +							'desc' => strip_tags($entity->description), +							'guid' => $entity->guid, +							'label' => $output, +							'value' => $entity->guid, +							'icon' => $icon, +							'url' => $entity->getURL(), +						); + +						$results[$entity->name . rand(1, 100)] = $result; +					} +				} +				break; + +			case 'friends': +				$query = "SELECT * FROM +						{$CONFIG->dbprefix}users_entity as ue, +						{$CONFIG->dbprefix}entity_relationships as er, +						{$CONFIG->dbprefix}entities as e +					WHERE er.relationship = 'friend' +						AND er.guid_one = {$user->getGUID()} +						AND er.guid_two = ue.guid +						AND e.guid = ue.guid +						AND e.enabled = 'yes' +						AND ue.banned = 'no' +						AND (ue.name LIKE '$q%' OR ue.name LIKE '% $q%' OR ue.username LIKE '$q%') +					LIMIT $limit +				"; + +				if ($entities = get_data($query)) { +					foreach ($entities as $entity) { +						// @todo use elgg_get_entities (don't query in a loop!) +						$entity = get_entity($entity->guid); +						/* @var ElggUser $entity */ +						if (!$entity) { +							continue; +						} + +						$output = elgg_view_list_item($entity, array( +							'use_hover' => false, +							'class' => 'elgg-autocomplete-item', +						)); + +						$icon = elgg_view_entity_icon($entity, 'tiny', array( +							'use_hover' => false, +						)); + +						$result = array( +							'type' => 'user', +							'name' => $entity->name, +							'desc' => $entity->username, +							'guid' => $entity->guid, +							'label' => $output, +							'value' => $entity->username, +							'icon' => $icon, +							'url' => $entity->getURL(), +						); +						$results[$entity->name . rand(1, 100)] = $result; +					} +				} +				break; + +			default: +				header("HTTP/1.0 400 Bad Request", true); +				echo "livesearch: unknown match_on of $match_type"; +				exit; +				break; +		} +	} + +	ksort($results); +	header("Content-Type: application/json"); +	echo json_encode(array_values($results)); +	exit; +} + +/** + * Register input functions and sanitize input + * + * @return void + * @access private + */ +function input_init() { +	// register an endpoint for live search / autocomplete. +	elgg_register_page_handler('livesearch', 'input_livesearch_page_handler'); + +	if (ini_get_bool('magic_quotes_gpc')) { + +		/** +		 * do keys as well, cos array_map ignores them +		 * +		 * @param array $array Array of values +		 * +		 * @return array Sanitized array +		 */ +		function stripslashes_arraykeys($array) { +			if (is_array($array)) { +				$array2 = array(); +				foreach ($array as $key => $data) { +					if ($key != stripslashes($key)) { +						$array2[stripslashes($key)] = $data; +					} else { +						$array2[$key] = $data; +					} +				} +				return $array2; +			} else { +				return $array; +			} +		} + +		/** +		 * Strip slashes on everything +		 * +		 * @param mixed $value The value to remove slashes from +		 * +		 * @return mixed +		 */ +		function stripslashes_deep($value) { +			if (is_array($value)) { +				$value = stripslashes_arraykeys($value); +				$value = array_map('stripslashes_deep', $value); +			} else { +				$value = stripslashes($value); +			} +			return $value; +		} + +		$_POST = stripslashes_arraykeys($_POST); +		$_GET = stripslashes_arraykeys($_GET); +		$_COOKIE = stripslashes_arraykeys($_COOKIE); +		$_REQUEST = stripslashes_arraykeys($_REQUEST); + +		$_POST = array_map('stripslashes_deep', $_POST); +		$_GET = array_map('stripslashes_deep', $_GET); +		$_COOKIE = array_map('stripslashes_deep', $_COOKIE); +		$_REQUEST = array_map('stripslashes_deep', $_REQUEST); +		if (!empty($_SERVER['REQUEST_URI'])) { +			$_SERVER['REQUEST_URI'] = stripslashes($_SERVER['REQUEST_URI']); +		} +		if (!empty($_SERVER['QUERY_STRING'])) { +			$_SERVER['QUERY_STRING'] = stripslashes($_SERVER['QUERY_STRING']); +		} +		if (!empty($_SERVER['HTTP_REFERER'])) { +			$_SERVER['HTTP_REFERER'] = stripslashes($_SERVER['HTTP_REFERER']); +		} +		if (!empty($_SERVER['PATH_INFO'])) { +			$_SERVER['PATH_INFO'] = stripslashes($_SERVER['PATH_INFO']); +		} +		if (!empty($_SERVER['PHP_SELF'])) { +			$_SERVER['PHP_SELF'] = stripslashes($_SERVER['PHP_SELF']); +		} +		if (!empty($_SERVER['PATH_TRANSLATED'])) { +			$_SERVER['PATH_TRANSLATED'] = stripslashes($_SERVER['PATH_TRANSLATED']); +		} +	} +} + +elgg_register_event_handler('init', 'system', 'input_init'); | 
