diff options
39 files changed, 500 insertions, 206 deletions
| diff --git a/actions/friends/collections/add.php b/actions/friends/collections/add.php index 8ec6a085f..8383e4db2 100644 --- a/actions/friends/collections/add.php +++ b/actions/friends/collections/add.php @@ -2,35 +2,31 @@  /**   * Elgg collection add page   * - * @package Elgg.Core - * @subpackage Friends.Collections + * @package Elgg + * @subpackage Core   */  $collection_name = get_input('collection_name');  $friends = get_input('friends_collection'); -//first check to make sure that a collection name has been set and create the new colection -if ($collection_name) { +if (!$collection_name) { +	register_error(elgg_echo("friends:nocollectionname")); +	forward(REFERER); +} -	//create the collection -	$create_collection = create_access_collection($collection_name, elgg_get_logged_in_user_guid()); +$id = create_access_collection($collection_name); -	//if the collection was created and the user passed some friends from the form, add them -	if ($create_collection && (!empty($friends))) { -		//add friends to the collection -		foreach ($friends as $friend) { -			add_user_to_access_collection($friend, $create_collection); -		} +if ($id) { +	$result = update_access_collection($id, $friends); +	if ($result) { +		system_message(elgg_echo("friends:collectionadded")); +		// go to the collections page +		forward("pg/collections/" . get_loggedin_user()->username); +	} else { +		register_error(elgg_echo("friends:nocollectionname")); +		forward(REFERER);  	} - -	// Success message -	system_message(elgg_echo("friends:collectionadded")); -	// Forward to the collections page -	forward("collections/" . elgg_get_logged_in_user_entity()->username); -  } else {  	register_error(elgg_echo("friends:nocollectionname")); - -	// Forward to the add collection page -	forward("collections/add"); +	forward(REFERER);  } diff --git a/actions/friends/collections/delete.php b/actions/friends/collections/delete.php index fe719d74b..5b0aa8e10 100644 --- a/actions/friends/collections/delete.php +++ b/actions/friends/collections/delete.php @@ -1,36 +1,24 @@  <?php +  /**   * Elgg friends: delete collection action   * - * @package Elgg.Core - * @subpackage Friends.Collections + * @package Elgg + * @subpackage Core   */  $collection_id = (int) get_input('collection'); -// Check to see that the access collection exist and grab its owner -$get_collection = get_access_collection($collection_id); - -if ($get_collection) { - -	if ($get_collection->owner_guid == elgg_get_logged_in_user_guid()) { - -		$delete_collection = delete_access_collection($collection_id); +// check the ACL exists and we can edit +if (!can_edit_access_collection($collection_id)) { +	register_error(elgg_echo("friends:collectiondeletefailed")); +	forward(REFERER); +} -		// Success message -		if ($delete_collection) { -			system_message(elgg_echo("friends:collectiondeleted")); -		} else { -			register_error(elgg_echo("friends:collectiondeletefailed")); -		} -	} else { -		// Failure message -		register_error(elgg_echo("friends:collectiondeletefailed")); -	} +if (delete_access_collection($collection_id)) { +	system_message(elgg_echo("friends:collectiondeleted"));  } else { -	// Failure message  	register_error(elgg_echo("friends:collectiondeletefailed"));  } -// Forward to the collections page -forward("collections/" . elgg_get_logged_in_user_entity()->username); +forward(REFERER); diff --git a/actions/friends/collections/edit.php b/actions/friends/collections/edit.php index b7fb716f2..581b21353 100644 --- a/actions/friends/collections/edit.php +++ b/actions/friends/collections/edit.php @@ -1,15 +1,23 @@  <?php  /** - * Friends collection edit action + * Elgg collection add page   * - * @package Elgg.Core - * @subpackage Friends.Collections + * @package Elgg + * @subpackage Core   */  $collection_id = get_input('collection_id');  $friends = get_input('friend'); -//chech the collection exists and the current user owners it -update_access_collection($collection_id, $friends); +// check it exists and we can edit +if (!can_edit_access_collection($collection_id)) { +	system_message(elgg_echo('friends:collection:edit_failed')); +} -exit; +if (update_access_collection($collection_id, $friends)) { +	system_message(elgg_echo('friends:collections:edited')); +} else { +	system_message(elgg_echo('friends:collection:edit_failed')); +} + +forward(REFERER);
\ No newline at end of file diff --git a/engine/classes/ElggCache.php b/engine/classes/ElggCache.php index 2e697e0bb..5c2cafcb7 100644 --- a/engine/classes/ElggCache.php +++ b/engine/classes/ElggCache.php @@ -6,9 +6,7 @@   * @package    Elgg.Core   * @subpackage Cache   */ -abstract class ElggCache implements -	// Override for array access -	ArrayAccess  { +abstract class ElggCache implements ArrayAccess {  	/**  	 * Variables for the cache object.  	 * @@ -141,6 +139,9 @@ abstract class ElggCache implements  	/**  	 * Load data from the cache using a given key.  	 * +	 * @todo $offset is a horrible variable name because it creates confusion +	 * with the ArrayAccess methods +	 *  	 * @param string $key    Name  	 * @param int    $offset Offset  	 * @param int    $limit  Limit @@ -186,12 +187,12 @@ abstract class ElggCache implements  	// ARRAY ACCESS INTERFACE //////////////////////////////////////////////////////////  	/** -	 * Set offset +	 * Assigns a value for the specified key  	 *  	 * @see ArrayAccess::offsetSet()  	 * -	 * @param mixed $key   Name -	 * @param mixed $value Value +	 * @param mixed $key    The key (offset) to assign the value to. +	 * @param mixed $value  The value to set.  	 *  	 * @return void  	 */ @@ -200,43 +201,43 @@ abstract class ElggCache implements  	}  	/** -	 * Get offset +	 * Get the value for specified key  	 *  	 * @see ArrayAccess::offsetGet()  	 * -	 * @param mixed $key Name +	 * @param mixed $offset The key (offset) to retrieve.  	 * -	 * @return void +	 * @return mixed  	 */  	function offsetGet($key) {  		return $this->load($key);  	}  	/** -	 * Unsets offset +	 * Unsets a key.  	 *  	 * @see ArrayAccess::offsetUnset()  	 * -	 * @param mixed $key Name +	 * @param mixed $key The key (offset) to unset.  	 *  	 * @return void  	 */  	function offsetUnset($key) { -		if (isset($this->key)) { -			unset($this->key); +		if (isset($this->$key)) { +			unset($this->$key);  		}  	}  	/** -	 * Does offset exist +	 * Does key exist  	 *  	 * @see ArrayAccess::offsetExists()  	 * -	 * @param mixed $offset Offset +	 * @param mixed $key A key (offset) to check for.  	 * -	 * @return void +	 * @return bool  	 */ -	function offsetExists($offset) { -		return isset($this->$offset); +	function offsetExists($key) { +		return isset($this->$key);  	}  } diff --git a/engine/classes/ElggUser.php b/engine/classes/ElggUser.php index 1af4cdc3a..75ac008f6 100644 --- a/engine/classes/ElggUser.php +++ b/engine/classes/ElggUser.php @@ -484,7 +484,8 @@ class ElggUser extends ElggEntity  	 * @return array|false  	 */  	public function getCollections($subtype = "", $limit = 10, $offset = 0) { -		return get_user_collections($this->getGUID(), $subtype, $limit, $offset); +		elgg_deprecated_notice("ElggUser::getCollections() has been deprecated", 1.8); +		return false;  	}  	/** diff --git a/engine/lib/access.php b/engine/lib/access.php index cde3d256f..ab4580bae 100644 --- a/engine/lib/access.php +++ b/engine/lib/access.php @@ -411,7 +411,43 @@ function get_write_access_array($user_id = 0, $site_id = 0, $flush = false) {  }  /** - * Creates a new access collection. + * Can the user write to the access collection? + * + * Hook into the access:collections:write, user to change this. + * + * Respects access control disabling for admin users and {@see elgg_set_ignore_access()} + * + * @see get_write_access_array() + *  + * @param int   $collection_id The collection id + * @param mixed $user_guid     The user GUID to check for. Defaults to logged in user. + * @return bool + */ +function can_edit_access_collection($collection_id, $user_guid = null) { +	if ($user_guid) { +		$user = get_entity((int) $user_guid); +	} else { +		$user = get_loggedin_user(); +	} + +	$collection = get_access_collection($collection_id); + +	if (!($user instanceof ElggUser) || !$collection) { +		return false; +	} + +	$write_access = get_write_access_array($user->getGUID(), null, true); + +	// don't ignore access when checking users. +	if ($user_guid) { +		return array_key_exists($collection_id, $write_access); +	} else { +		return elgg_get_ignore_access() || array_key_exists($collection_id, $write_access); +	} +} + +/** + * Creates a new access control collection owned by the specified user.   *   * Access colletions allow plugins and users to create granular access   * for entities. @@ -448,6 +484,7 @@ function create_access_collection($name, $owner_guid = 0, $site_guid = 0) {  		SET name = '{$name}',  			owner_guid = {$owner_guid},  			site_guid = {$site_guid}"; +  	if (!$id = insert_data($q)) {  		return false;  	} @@ -483,37 +520,31 @@ function create_access_collection($name, $owner_guid = 0, $site_guid = 0) {  function update_access_collection($collection_id, $members) {  	global $CONFIG; -	$collection_id = (int) $collection_id; -	$members = (is_array($members)) ? $members : array(); +	$acl = get_access_collection($collection_id); -	$collections = get_write_access_array(); +	if (!$acl) { +		return false; +	} -	if (array_key_exists($collection_id, $collections)) { -		$cur_members = get_members_of_access_collection($collection_id, true); -		$cur_members = (is_array($cur_members)) ? $cur_members : array(); +	$members = (is_array($members)) ? $members : array(); -		$remove_members = array_diff($cur_members, $members); -		$add_members = array_diff($members, $cur_members); +	$cur_members = get_members_of_access_collection($collection_id, true); +	$cur_members = (is_array($cur_members)) ? $cur_members : array(); -		$params = array( -			'collection_id' => $collection_id, -			'members' => $members, -			'add_members' => $add_members, -			'remove_members' => $remove_members -		); +	$remove_members = array_diff($cur_members, $members); +	$add_members = array_diff($members, $cur_members); -		foreach ($add_members as $guid) { -			add_user_to_access_collection($guid, $collection_id); -		} +	$result = true; -		foreach ($remove_members as $guid) { -			remove_user_from_access_collection($guid, $collection_id); -		} +	foreach ($add_members as $guid) { +		$result = $result && add_user_to_access_collection($guid, $collection_id); +	} -		return true; +	foreach ($remove_members as $guid) { +		$result = $result && remove_user_from_access_collection($guid, $collection_id);  	} -	return false; +	return $result;  }  /** @@ -527,27 +558,25 @@ function update_access_collection($collection_id, $members) {   * @see update_access_collection()   */  function delete_access_collection($collection_id) { +	global $CONFIG; +	  	$collection_id = (int) $collection_id; -	$collections = get_write_access_array(null, null, TRUE);  	$params = array('collection_id' => $collection_id);  	if (!elgg_trigger_plugin_hook('access:collections:deletecollection', 'collection', $params, true)) {  		return false;  	} -	if (array_key_exists($collection_id, $collections)) { -		global $CONFIG; -		$query = "delete from {$CONFIG->dbprefix}access_collection_membership" -			. " where access_collection_id = {$collection_id}"; -		delete_data($query); +	// Deleting membership doesn't affect result of deleting ACL. +	$q = "DELETE FROM {$CONFIG->dbprefix}access_collection_membership +		WHERE access_collection_id = {$collection_id}"; +	delete_data($q); -		$query = "delete from {$CONFIG->dbprefix}access_collections where id = {$collection_id}"; -		delete_data($query); -		return true; -	} else { -		return false; -	} +	$q = "DELETE FROM {$CONFIG->dbprefix}access_collections +		WHERE id = {$collection_id}"; +	$result = delete_data($q); +	return $result;  }  /** @@ -584,45 +613,33 @@ function get_access_collection($collection_id) {   * @see remove_user_from_access_collection()   */  function add_user_to_access_collection($user_guid, $collection_id) { +	global $CONFIG; +  	$collection_id = (int) $collection_id;  	$user_guid = (int) $user_guid; -	$collections = get_write_access_array(); +	$user = get_user($user_guid); -	if (!($collection = get_access_collection($collection_id))) { -		return false; -	} +	$collection = get_access_collection($collection_id); -	$user = get_user($user_guid); -	if (!$user) { +	if (!($user instanceof Elgguser) || !$collection) {  		return false;  	} -	// to add someone to a collection, the user must be a member of the collection or -	// no one must own it -	if ((array_key_exists($collection_id, $collections) || $collection->owner_guid == 0)) { -		$result = true; -	} else { -		$result = false; -	} -	  	$params = array(  		'collection_id' => $collection_id, -		'collection' => $collection,  		'user_guid' => $user_guid  	); -	$result = elgg_trigger_plugin_hook('access:collections:add_user', 'collection', $params, $result); -	if ($result == false) { +	if (!elgg_trigger_plugin_hook('access:collections:add_user', 'collection', $params, true)) {  		return false;  	}  	try { -		global $CONFIG; -		$query = "insert into {$CONFIG->dbprefix}access_collection_membership" -				. " set access_collection_id = {$collection_id}, user_guid = {$user_guid}"; -		insert_data($query); +		$q = "INSERT INTO {$CONFIG->dbprefix}access_collection_membership +			SET access_collection_id = {$collection_id}, +				user_guid = {$user_guid}"; +		insert_data($q);  	} catch (DatabaseException $e) { -		// nothing.  		return false;  	} @@ -640,34 +657,32 @@ function add_user_to_access_collection($user_guid, $collection_id) {   * @return true|false Depending on success   */  function remove_user_from_access_collection($user_guid, $collection_id) { +	global $CONFIG; +  	$collection_id = (int) $collection_id;  	$user_guid = (int) $user_guid; -	$collections = get_write_access_array(); -	$user = $user = get_user($user_guid); +	$user = get_user($user_guid); + +	$collection = get_access_collection($collection_id); -	if (!($collection = get_access_collection($collection_id))) { +	if (!($user instanceof Elgguser) || !$collection) {  		return false;  	} -	if ((array_key_exists($collection_id, $collections) || $collection->owner_guid == 0) && $user) { -		global $CONFIG; -		$params = array( -			'collection_id' => $collection_id, -			'user_guid' => $user_guid -		); - -		if (!elgg_trigger_plugin_hook('access:collections:remove_user', 'collection', $params, true)) { -			return false; -		} - -		delete_data("delete from {$CONFIG->dbprefix}access_collection_membership " -			. "where access_collection_id = {$collection_id} and user_guid = {$user_guid}"); - -		return true; +	$params = array( +		'collection_id' => $collection_id, +		'user_guid' => $user_guid +	); +	if (!elgg_trigger_plugin_hook('access:collections:remove_user', 'collection', $params, true)) { +		return false;  	} -	return false; +	$q = "DELETE FROM {$CONFIG->dbprefix}access_collection_membership +		WHERE access_collection_id = {$collection_id} +			AND user_guid = {$user_guid}"; + +	return delete_data($q);  }  /** @@ -956,9 +971,20 @@ function elgg_override_permissions_hook() {  	return NULL;  } +/** + * Runs unit tests for the entities object. + */ +function access_test($hook, $type, $value, $params) { +	global $CONFIG; +	$value[] = $CONFIG->path . 'engine/tests/api/access_collections.php'; +	return $value; +} +  // This function will let us know when 'init' has finished  elgg_register_event_handler('init', 'system', 'access_init', 9999);  // For overrided permissions  elgg_register_plugin_hook_handler('permissions_check', 'all', 'elgg_override_permissions_hook');  elgg_register_plugin_hook_handler('container_permissions_check', 'all', 'elgg_override_permissions_hook'); + +elgg_register_plugin_hook_handler('unit_test', 'system', 'access_test'); diff --git a/engine/lib/input.php b/engine/lib/input.php index 84752bc7d..56ec214dc 100644 --- a/engine/lib/input.php +++ b/engine/lib/input.php @@ -10,8 +10,13 @@  /**   * Get some input from variables passed on the GET or POST line.   * + * 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?   *   * @param string $variable      The variable we want to return.   * @param mixed  $default       A default value for the variable if it is not found. diff --git a/engine/lib/navigation.php b/engine/lib/navigation.php index cdf3d0f67..1305ee3de 100644 --- a/engine/lib/navigation.php +++ b/engine/lib/navigation.php @@ -154,17 +154,20 @@ function elgg_is_menu_item_registered($menu_name, $item_name) {  }  /** - * Convenience function for registering an add content button to title menu + * Convenience function for registering a button to title menu   * - * The add URL must be $handler/add/$guid where $guid is the guid of the page owner. - * The label of the button is "$handler:add" so that must be defined in a + * The URL must be $handler/$name/$guid where $guid is the guid of the page owner. + * The label of the button is "$handler:$name" so that must be defined in a   * language file.   * + * This is used primarily to support adding an add content button + *   * @param string $handler The handler to use or null to autodetect from context + * @param string $name    Name of the button   * @return void   * @since 1.8.0   */ -function elgg_register_add_button($handler = null) { +function elgg_register_title_button($handler = null, $name = 'add') {  	if (elgg_is_logged_in()) {  		if (!$handler) { @@ -179,9 +182,9 @@ function elgg_register_add_button($handler = null) {  		if ($owner && $owner->canWriteToContainer()) {  			$guid = $owner->getGUID();  			elgg_register_menu_item('title', array( -				'name' => 'add', -				'href' => "$handler/add/$guid", -				'text' => elgg_echo("$handler:add"), +				'name' => $name, +				'href' => "$handler/$name/$guid", +				'text' => elgg_echo("$handler:$name"),  				'link_class' => 'elgg-button elgg-button-action',  			));  		} diff --git a/engine/lib/river.php b/engine/lib/river.php index 36dde7f05..1a2be1e50 100644 --- a/engine/lib/river.php +++ b/engine/lib/river.php @@ -589,10 +589,13 @@ function elgg_river_page_handler($page) {  	elgg_set_page_owner_guid(elgg_get_logged_in_user_guid()); +	// make a URL segment available in page handler script  	$page_type = elgg_extract(0, $page, 'all'); +	$page_type = preg_replace('[\W]', '', $page_type);  	if ($page_type == 'owner') {  		$page_type = 'mine';  	} +	set_input('page_type', $page_type);  	// content filter code here  	$entity_type = ''; diff --git a/engine/tests/api/access_collections.php b/engine/tests/api/access_collections.php new file mode 100644 index 000000000..d81589cc1 --- /dev/null +++ b/engine/tests/api/access_collections.php @@ -0,0 +1,260 @@ +<?php +/** + * Access Collections tests + * + * @package Elgg + * @subpackage Test + */ +class ElggCoreAccessCollectionsTest extends ElggCoreUnitTest { + +	/** +	 * Called before each test object. +	 */ +	public function __construct() { +		parent::__construct(); + +		$this->dbPrefix = get_config("dbprefix"); + +		$user = new ElggUser(); +		$user->username = 'test_user_' . rand(); +		$user->email = 'fake_email@fake.com' . rand(); +		$user->name = 'fake user'; +		$user->access_id = ACCESS_PUBLIC; +		$user->salt = generate_random_cleartext_password(); +		$user->password = generate_user_password($user, rand()); +		$user->owner_guid = 0; +		$user->container_guid = 0; +		$user->save(); + +		$this->user = $user; +	} + +	/** +	 * Called before each test method. +	 */ +	public function setUp() { + +	} + +	/** +	 * Called after each test method. +	 */ +	public function tearDown() { +		// do not allow SimpleTest to interpret Elgg notices as exceptions +		$this->swallowErrors(); +	} + +	/** +	 * Called after each test object. +	 */ +	public function __destruct() { +		// all __destruct() code should go above here +		$this->user->delete(); +		parent::__destruct(); +	} + +	public function testCreateGetDeleteACL() { +		global $DB_QUERY_CACHE; +		 +		$acl_name = 'test access collection'; +		$acl_id = create_access_collection($acl_name); + +		$this->assertTrue(is_int($acl_id)); + +		$q = "SELECT * FROM {$this->dbPrefix}access_collections WHERE id = $acl_id"; +		$acl = get_data_row($q); + +		$this->assertEqual($acl->id, $acl_id); + +		if ($acl) { +			$DB_QUERY_CACHE = array(); +			 +			$this->assertEqual($acl->name, $acl_name); + +			$result = delete_access_collection($acl_id); +			$this->assertTrue($result); + +			$q = "SELECT * FROM {$this->dbPrefix}access_collections WHERE id = $acl_id"; +			$data = get_data($q); +			$this->assertFalse($data); +		} +	} + +	public function testAddRemoveUserToACL() { +		$acl_id = create_access_collection('test acl'); + +		$result = add_user_to_access_collection($this->user->guid, $acl_id); +		$this->assertTrue($result); + +		if ($result) { +			$result = remove_user_from_access_collection($this->user->guid, $acl_id); +			$this->assertTrue($result); +		} + +		delete_access_collection($acl_id); +	} + +	public function testUpdateACL() { +		// another fake user to test with +		$user = new ElggUser(); +		$user->username = 'test_user_' . rand(); +		$user->email = 'fake_email@fake.com' . rand(); +		$user->name = 'fake user'; +		$user->access_id = ACCESS_PUBLIC; +		$user->salt = generate_random_cleartext_password(); +		$user->password = generate_user_password($user, rand()); +		$user->owner_guid = 0; +		$user->container_guid = 0; +		$user->save(); + +		$acl_id = create_access_collection('test acl'); + +		$member_lists = array( +			// adding +			array( +				$this->user->guid, +				$user->guid +			), +			// removing one, keeping one. +			array( +				$user->guid +			), +			// removing one, adding one +			array( +				$this->user->guid, +			), +			// removing all. +			array() +		); + +		foreach ($member_lists as $members) { +			$result = update_access_collection($acl_id, $members); +			$this->assertTrue($result); + +			if ($result) { +				$q = "SELECT * FROM {$this->dbPrefix}access_collection_membership +					WHERE access_collection_id = $acl_id"; +				$data = get_data($q); + +				if (count($members) == 0) { +					$this->assertFalse($data); +				} else { +					$this->assertEqual(count($members), count($data)); +				} +				foreach ($data as $row) { +					$this->assertTrue(in_array($row->user_guid, $members)); +				} +			} +		} + +		delete_access_collection($acl_id); +		$user->delete(); +	} + +	public function testCanEditACL() { +		$acl_id = create_access_collection('test acl', $this->user->guid); + +		// should be true since it's the owner +		$result = can_edit_access_collection($acl_id, $this->user->guid); +		$this->assertTrue($result); + +		// should be true since IA is on. +		$ia = elgg_set_ignore_access(true); +		$result = can_edit_access_collection($acl_id); +		$this->assertTrue($result); +		elgg_set_ignore_access($ia); + +		// should be false since IA is off +		$ia = elgg_set_ignore_access(false); +		$result = can_edit_access_collection($acl_id); +		$this->assertFalse($result); +		elgg_set_ignore_access($ia); + +		delete_access_collection($acl_id); +	} + +	public function testCanEditACLHook() { +		// if only we supported closures! +		global $acl_test_info; + +		$acl_id = create_access_collection('test acl'); + +		$acl_test_info = array( +			'acl_id' => $acl_id, +			'user' => $this->user +		); +		 +		function test_acl_access_hook($hook, $type, $value, $params) { +			global $acl_test_info; +			if ($params['user_id'] == $acl_test_info['user']->guid) { +				$acl = get_access_collection($acl_test_info['acl_id']); +				$value[$acl->id] = $acl->name; +			} + +			return $value; +		} + +		register_plugin_hook('access:collections:write', 'all', 'test_acl_access_hook'); + +		// enable security since we usually run as admin +		$ia = elgg_set_ignore_access(false); +		$result = can_edit_access_collection($acl_id, $this->user->guid); +		$this->assertTrue($result); +		$ia = elgg_set_ignore_access($ia); + +		unregister_plugin_hook('access:collections:write', 'all', 'test_acl_access_hook'); +	} + +	// groups interface +	// only runs if the groups plugin is enabled because implementation is split between +	// core and the plugin. +	public function testCreateDeleteGroupACL() { +		if (!is_plugin_enabled('groups')) { +			return; +		} +		 +		$group = new ElggGroup(); +		$group->name = 'Test group'; +		$group->save(); +		$acl = get_access_collection($group->group_acl); + +		// ACLs are owned by groups +		$this->assertEqual($acl->owner_guid, $group->guid); + +		// removing group and acl +		$this->assertTrue($group->delete()); +		 +		$acl = get_access_collection($group->group_acl); +		$this->assertFalse($acl); + +		$group->delete(); +	} + +	public function testJoinLeaveGroupACL() { +		if (!is_plugin_enabled('groups')) { +			return; +		} + +		$group = new ElggGroup(); +		$group->name = 'Test group'; +		$group->save(); + +		$result = $group->join($this->user); +		$this->assertTrue($result); + +		if ($result) { +			$can_edit = can_edit_access_collection($group->group_acl, $this->user->guid); +			$this->assertTrue($can_edit); +		} + +		$result = $group->leave($this->user); +		$this->assertTrue($result); + +		if ($result) { +			$can_edit = can_edit_access_collection($group->group_acl, $this->user->guid); +			$this->assertFalse($can_edit); +		} + +		$group->delete(); +	} +} diff --git a/languages/en.php b/languages/en.php index 72369c82f..b525a2043 100644 --- a/languages/en.php +++ b/languages/en.php @@ -343,6 +343,8 @@ $english = array(  	'friends:nocollectionname' => "You need to give your collection a name before it can be created.",  	'friends:collections:members' => "Collection members",  	'friends:collections:edit' => "Edit collection", +	'friends:collections:edited' => "Saved collection", +	'friends:collection:edit_failed' => 'Could not save collection.',  	'friendspicker:chararray' => 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', @@ -857,6 +859,7 @@ $english = array(  	'mine' => "Mine",  	'by' => 'by', +	'none' => 'none',  	'annotations' => "Annotations",  	'relationships' => "Relationships", diff --git a/mod/blog/languages/en.php b/mod/blog/languages/en.php index 47dc57dda..8a21c1f8d 100644 --- a/mod/blog/languages/en.php +++ b/mod/blog/languages/en.php @@ -53,10 +53,12 @@ $english = array(  	'blog:error:revision_not_found' => 'Cannot find this revision.',  	// river -	  	'river:create:object:blog' => '%s published a blog post %s',  	'river:comment:object:blog' => '%s commented on the blog %s', +	// notifications +	'blog:newpost' => 'A new blog post', +  	// widget  	'blog:widget:description' => 'Display your latest blog posts',  	'blog:moreblogs' => 'More blog posts', diff --git a/mod/blog/lib/blog.php b/mod/blog/lib/blog.php index 0f81597eb..b7b1a2baa 100644 --- a/mod/blog/lib/blog.php +++ b/mod/blog/lib/blog.php @@ -92,7 +92,7 @@ function blog_get_page_content_list($container_guid = NULL) {  		elgg_push_breadcrumb(elgg_echo('blog:blogs'));  	} -	elgg_register_add_button(); +	elgg_register_title_button();  	// show all posts for admin or users looking at their own blogs  	// show only published posts for other users. @@ -131,7 +131,7 @@ function blog_get_page_content_friends($user_guid) {  	elgg_push_breadcrumb($crumbs_title, "blog/owner/{$user->username}");  	elgg_push_breadcrumb(elgg_echo('friends')); -	elgg_register_add_button(); +	elgg_register_title_button();  	if (!$friends = get_user_friends($user_guid, ELGG_ENTITIES_ANY_VALUE, 0)) {  		$return['content'] .= elgg_echo('friends:none:you'); diff --git a/mod/bookmarks/pages/bookmarks/all.php b/mod/bookmarks/pages/bookmarks/all.php index 7b3f2059c..d9ac2767f 100644 --- a/mod/bookmarks/pages/bookmarks/all.php +++ b/mod/bookmarks/pages/bookmarks/all.php @@ -8,7 +8,7 @@  elgg_pop_breadcrumb();  elgg_push_breadcrumb(elgg_echo('bookmarks')); -elgg_register_add_button(); +elgg_register_title_button();  $offset = (int)get_input('offset', 0);  $content = elgg_list_entities(array( diff --git a/mod/bookmarks/pages/bookmarks/friends.php b/mod/bookmarks/pages/bookmarks/friends.php index ef5f078f5..3491090a5 100644 --- a/mod/bookmarks/pages/bookmarks/friends.php +++ b/mod/bookmarks/pages/bookmarks/friends.php @@ -10,7 +10,7 @@ $owner = elgg_get_page_owner_entity();  elgg_push_breadcrumb($owner->name, "bookmarks/owner/$owner->username");  elgg_push_breadcrumb(elgg_echo('friends')); -elgg_register_add_button(); +elgg_register_title_button();  $title = elgg_echo('bookmarks:friends'); diff --git a/mod/bookmarks/pages/bookmarks/owner.php b/mod/bookmarks/pages/bookmarks/owner.php index 46a22080d..679c986be 100644 --- a/mod/bookmarks/pages/bookmarks/owner.php +++ b/mod/bookmarks/pages/bookmarks/owner.php @@ -9,7 +9,7 @@ $page_owner = elgg_get_page_owner_entity();  elgg_push_breadcrumb($page_owner->name); -elgg_register_add_button(); +elgg_register_title_button();  $offset = (int)get_input('offset', 0);  $content .= elgg_list_entities(array( diff --git a/mod/custom_index/views/default/page/layouts/custom_index.php b/mod/custom_index/views/default/page/layouts/custom_index.php index 0883e7274..6b3f6d739 100644 --- a/mod/custom_index/views/default/page/layouts/custom_index.php +++ b/mod/custom_index/views/default/page/layouts/custom_index.php @@ -17,7 +17,7 @@  // Top box for login or welcome message  if (elgg_is_logged_in()) {  	$top_box = "<h2>" . elgg_echo("welcome") . " "; -	$top_box .= get_loggedin_user()->name; +	$top_box .= elgg_get_logged_in_user_entity()->name;  	$top_box .= "</h2>";  } else {  	$top_box = $vars['login']; diff --git a/mod/embed/start.php b/mod/embed/start.php index f6f1acc57..bdd832b4e 100644 --- a/mod/embed/start.php +++ b/mod/embed/start.php @@ -81,8 +81,10 @@ function embed_page_handler($page) {  			elgg_sort_3d_array_by_value($sections, 'name');  			elgg_sort_3d_array_by_value($upload_sections, 'name'); -			$active_section = get_input('active_section', NULL); -			$internal_id = get_input('internal_id', NULL); +			$active_section = get_input('active_section', ''); +			$active_section = preg_replace('[\W]', '', $active_section); +			$internal_id = get_input('internal_id', ''); +			$internal_id = preg_replace('[\W]', '', $internal_id);  			echo elgg_view('embed/embed', array(  				'sections' => $sections, diff --git a/mod/embed/views/default/embed/css.php b/mod/embed/views/default/embed/css.php index 1ce994cfe..150dc8733 100644 --- a/mod/embed/views/default/embed/css.php +++ b/mod/embed/views/default/embed/css.php @@ -14,7 +14,7 @@  	color: #333333;  	margin-bottom: 10px;  } -.embed-wrapper .elgg-list-item { +.embed-wrapper .elgg-item {  	cursor: pointer;  } diff --git a/mod/embed/views/default/embed/embed.php b/mod/embed/views/default/embed/embed.php index 77ce03699..2d8de1ca4 100644 --- a/mod/embed/views/default/embed/embed.php +++ b/mod/embed/views/default/embed/embed.php @@ -10,7 +10,7 @@   */  $sections = elgg_extract('sections', $vars, array()); -$active_section = elgg_extract('active_section', $vars, array_shift(array_keys($sections))); +$active_section = elgg_extract('active_section', $vars, array_shift(array_keys($sections)), false);  $upload_sections = elgg_extract('upload_sections', $vars, array());  $internal_id = elgg_extract('internal_id', $vars); @@ -20,8 +20,8 @@ if (!$sections) {  	$content = elgg_view_title(elgg_echo('embed:media'));  	$content .= elgg_view('embed/tabs', $vars); -	$offset = max(0, get_input('offset', 0)); -	$limit = get_input('limit', 5); +	$offset = (int)max(0, get_input('offset', 0)); +	$limit = (int)get_input('limit', 5);  	// build the items and layout.  	if ($active_section == 'upload' || array_key_exists($active_section, $sections)) { diff --git a/mod/embed/views/default/embed/upload/content.php b/mod/embed/views/default/embed/upload/content.php index 24fce8112..8bedf5ad1 100644 --- a/mod/embed/views/default/embed/upload/content.php +++ b/mod/embed/views/default/embed/upload/content.php @@ -4,6 +4,7 @@   */  $upload_sections = elgg_extract('upload_sections', $vars, array());  $active_section = get_input('active_upload_section', array_shift(array_keys($upload_sections))); +$active_section = preg_replace('[\W]', '', $active_section);  $options = array(); diff --git a/mod/embed/views/default/js/embed/embed.php b/mod/embed/views/default/js/embed/embed.php index bf04c0963..ea92ba1fd 100644 --- a/mod/embed/views/default/js/embed/embed.php +++ b/mod/embed/views/default/js/embed/embed.php @@ -3,7 +3,7 @@ elgg.provide('elgg.embed');  elgg.embed.init = function() {  	// inserts the embed content into the textarea -	$(".embed-wrapper .elgg-list-item").live('click', elgg.embed.insert); +	$(".embed-wrapper .elgg-item").live('click', elgg.embed.insert);  	// caches the current textarea id  	$(".embed-control").live('click', function() { diff --git a/mod/file/pages/file/friends.php b/mod/file/pages/file/friends.php index 7bde42962..0b351efaf 100644 --- a/mod/file/pages/file/friends.php +++ b/mod/file/pages/file/friends.php @@ -11,7 +11,7 @@ elgg_push_breadcrumb(elgg_echo('file'), "file/all");  elgg_push_breadcrumb($owner->name, "file/owner/$owner->username");  elgg_push_breadcrumb(elgg_echo('friends')); -elgg_register_add_button(); +elgg_register_title_button();  $title = elgg_echo("file:friends"); diff --git a/mod/file/pages/file/owner.php b/mod/file/pages/file/owner.php index 2244de095..4e2ec89d4 100644 --- a/mod/file/pages/file/owner.php +++ b/mod/file/pages/file/owner.php @@ -13,7 +13,7 @@ $owner = elgg_get_page_owner_entity();  elgg_push_breadcrumb(elgg_echo('file'), "file/all");  elgg_push_breadcrumb($owner->name); -elgg_register_add_button(); +elgg_register_title_button();  $params = array(); diff --git a/mod/file/pages/file/search.php b/mod/file/pages/file/search.php index cffe67e0c..2242d1d7e 100644 --- a/mod/file/pages/file/search.php +++ b/mod/file/pages/file/search.php @@ -5,7 +5,7 @@   * @package ElggFile   */ -$page_owner_guid = get_input('page_owner', null); +$page_owner_guid = (int)get_input('page_owner', 0);  if ($page_owner_guid) {  	elgg_set_page_owner_guid($page_owner_guid);  } @@ -15,10 +15,10 @@ group_gatekeeper();  // Get input  $md_type = 'simpletype'; -$tag = get_input('tag'); +// avoid reflected XSS attacks by only allowing alnum characters +$file_type = preg_replace('[\W]', '', get_input('tag'));  $listtype = get_input('listtype'); -$friends = get_input('friends', false); - +$friends = (bool)get_input('friends', false);  // breadcrumbs  elgg_push_breadcrumb(elgg_echo('file'), "file/all"); @@ -32,8 +32,8 @@ if ($owner) {  if ($friends && $owner) {  	elgg_push_breadcrumb(elgg_echo('friends'), "file/friends/$owner->username");  } -if ($tag) { -	elgg_push_breadcrumb(elgg_echo("file:type:$tag")); +if ($file_type) { +	elgg_push_breadcrumb(elgg_echo("file:type:$file_type"));  } else {  	elgg_push_breadcrumb(elgg_echo('all'));  } @@ -41,10 +41,10 @@ if ($tag) {  // title  if (!$owner) {  	// world files -	$title = elgg_echo('all') . ' ' . elgg_echo("file:type:$tag"); +	$title = elgg_echo('all') . ' ' . elgg_echo("file:type:$file_type");  } else {  	$friend_string = $friends ? elgg_echo('file:title:friends') : ''; -	$type_string = elgg_echo("file:type:$tag"); +	$type_string = elgg_echo("file:type:$file_type");  	$title = elgg_echo('file:list:title', array($owner->name, $friend_string, $type_string));  } @@ -76,9 +76,9 @@ $params = array(  	'full_view' => false,  ); -if ($tag) { +if ($file_type) {  	$params['metadata_name'] = $md_type; -	$params['metadata_value'] = $tag; +	$params['metadata_value'] = $file_type;  	$content = elgg_list_entities_from_metadata($params);  } else {  	$content = elgg_list_entities($params); diff --git a/mod/file/pages/file/world.php b/mod/file/pages/file/world.php index 560743bed..e438ca2f0 100644 --- a/mod/file/pages/file/world.php +++ b/mod/file/pages/file/world.php @@ -7,7 +7,7 @@  elgg_push_breadcrumb(elgg_echo('file')); -elgg_register_add_button(); +elgg_register_title_button();  $limit = get_input("limit", 10); diff --git a/mod/groups/lib/discussion.php b/mod/groups/lib/discussion.php index 52df7e18d..e129e0f9d 100644 --- a/mod/groups/lib/discussion.php +++ b/mod/groups/lib/discussion.php @@ -45,7 +45,7 @@ function discussion_handle_list_page($guid) {  	}  	elgg_push_breadcrumb($group->name); -	elgg_register_add_button(); +	elgg_register_title_button();  	group_gatekeeper(); diff --git a/mod/groups/lib/groups.php b/mod/groups/lib/groups.php index 2747f360b..126738566 100644 --- a/mod/groups/lib/groups.php +++ b/mod/groups/lib/groups.php @@ -12,7 +12,7 @@ function groups_handle_all_page() {  	elgg_pop_breadcrumb();  	elgg_push_breadcrumb(elgg_echo('groups')); -	elgg_register_add_button(); +	elgg_register_title_button();  	$selected_tab = get_input('filter', 'newest'); @@ -100,7 +100,7 @@ function groups_handle_owned_page() {  	$title = elgg_echo('groups:owned');  	elgg_push_breadcrumb($title); -	elgg_register_add_button(); +	elgg_register_title_button();  	$content = elgg_list_entities(array(  		'type' => 'group', @@ -128,7 +128,7 @@ function groups_handle_mine_page() {  	$title = elgg_echo('groups:yours');  	elgg_push_breadcrumb($title); -	elgg_register_add_button(); +	elgg_register_title_button();  	$content = elgg_list_entities_from_relationship_count(array(  		'type' => 'group', diff --git a/mod/messages/pages/messages/inbox.php b/mod/messages/pages/messages/inbox.php index 96712a193..fdfc20c43 100644 --- a/mod/messages/pages/messages/inbox.php +++ b/mod/messages/pages/messages/inbox.php @@ -15,7 +15,7 @@ if (!$page_owner) {  elgg_push_breadcrumb(elgg_echo('messages:inbox')); -elgg_register_add_button(); +elgg_register_title_button();  $title = elgg_echo('messages:user', array($page_owner->name)); diff --git a/mod/messages/pages/messages/send.php b/mod/messages/pages/messages/send.php index 02d430df7..1b821d185 100644 --- a/mod/messages/pages/messages/send.php +++ b/mod/messages/pages/messages/send.php @@ -14,7 +14,7 @@ $title = elgg_echo('messages:add');  elgg_push_breadcrumb($title); -$params = messages_prepare_form_vars(get_input('send_to')); +$params = messages_prepare_form_vars((int)get_input('send_to'));  $params['friends'] = $page_owner->getFriends();  $content = elgg_view_form('messages/send', array(), $params); diff --git a/mod/messages/pages/messages/sent.php b/mod/messages/pages/messages/sent.php index edf2b29fb..af06ab273 100644 --- a/mod/messages/pages/messages/sent.php +++ b/mod/messages/pages/messages/sent.php @@ -15,7 +15,7 @@ if (!$page_owner) {  elgg_push_breadcrumb(elgg_echo('messages:sent')); -elgg_register_add_button(); +elgg_register_title_button();  $title = elgg_echo('messages:sentmessages', array($page_owner->name)); diff --git a/mod/notifications/start.php b/mod/notifications/start.php index 0f1e11a57..c6701cc3e 100644 --- a/mod/notifications/start.php +++ b/mod/notifications/start.php @@ -1,11 +1,11 @@  <?php -  /**   * Elgg notifications plugin   *   * @package ElggNotifications   */ +elgg_register_event_handler('init', 'system', 'notifications_plugin_init');  function notifications_plugin_init() { @@ -187,5 +187,3 @@ function notifications_update_collection_notify($event, $object_type, $returnval  		}  	}  } - -elgg_register_event_handler('init', 'system', 'notifications_plugin_init', 1000); diff --git a/mod/pages/pages/pages/friends.php b/mod/pages/pages/pages/friends.php index 88f26c45d..c55b27466 100644 --- a/mod/pages/pages/pages/friends.php +++ b/mod/pages/pages/pages/friends.php @@ -13,7 +13,7 @@ if (!$owner) {  elgg_push_breadcrumb($owner->name, "pages/owner/$owner->username");  elgg_push_breadcrumb(elgg_echo('friends')); -elgg_register_add_button(); +elgg_register_title_button();  $title = elgg_echo('pages:friends'); diff --git a/mod/pages/pages/pages/owner.php b/mod/pages/pages/pages/owner.php index 312b56a54..2ff310ac8 100644 --- a/mod/pages/pages/pages/owner.php +++ b/mod/pages/pages/pages/owner.php @@ -17,7 +17,7 @@ $title = elgg_echo('pages:owner', array($owner->name));  elgg_push_breadcrumb($owner->name); -elgg_register_add_button(); +elgg_register_title_button();  $content = elgg_list_entities(array(  	'types' => 'object', diff --git a/mod/pages/pages/pages/world.php b/mod/pages/pages/pages/world.php index 9237a820e..e6a705b6b 100644 --- a/mod/pages/pages/pages/world.php +++ b/mod/pages/pages/pages/world.php @@ -10,7 +10,7 @@ $title = elgg_echo('pages:all');  elgg_pop_breadcrumb();  elgg_push_breadcrumb(elgg_echo('pages')); -elgg_register_add_button(); +elgg_register_title_button();  $content = elgg_list_entities(array(  	'types' => 'object', diff --git a/mod/tinymce/start.php b/mod/tinymce/start.php index 3b662308a..ee7154d22 100644 --- a/mod/tinymce/start.php +++ b/mod/tinymce/start.php @@ -5,6 +5,8 @@   * @package ElggTinyMCE   */ +elgg_register_event_handler('init', 'system', 'tinymce_init'); +  function tinymce_init() {  	elgg_extend_view('css/elgg', 'tinymce/css');  	elgg_extend_view('css/admin', 'tinymce/css'); @@ -30,5 +32,3 @@ function tinymce_longtext_menu($hook, $type, $items, $vars) {  	return $items;  } - -elgg_register_event_handler('init', 'system', 'tinymce_init', 9999); diff --git a/pages/river.php b/pages/river.php index fa559d59b..5770084ab 100644 --- a/pages/river.php +++ b/pages/river.php @@ -3,12 +3,12 @@   * Main activity stream list page   */ -// $page_type comes from the page handler function -  $options = array(); -$type = get_input('type', 'all'); -$subtype = get_input('subtype', ''); +$page_type = preg_replace('[\W]', '', get_input('page_type', 'all')); +$type = preg_replace('[\W]', '', get_input('type', 'all')); +$active_section = +$subtype = preg_replace('[\W]', '', get_input('subtype', ''));  if ($subtype) {  	$selector = "type=$type&subtype=$subtype";  } else { diff --git a/views/default/css/admin.php b/views/default/css/admin.php index e8705583f..2d587fcbe 100644 --- a/views/default/css/admin.php +++ b/views/default/css/admin.php @@ -428,15 +428,10 @@ input {  	border-radius: 5px;  }  /* default elgg core input field classes */ -.input-text, -.input-tags, -.input-url, -.input-textarea, -<?php // until we're all on elgg-, need to duplicate ?>  .elgg-input-text,  .elgg-input-tags,  .elgg-input-url, -.elgg-input-textarea { +.elgg-input-plaintext {  	width:98%;  }  textarea { diff --git a/views/default/page/elements/header_logo.php b/views/default/page/elements/header_logo.php index 4295deaa4..7fe721c40 100644 --- a/views/default/page/elements/header_logo.php +++ b/views/default/page/elements/header_logo.php @@ -1,13 +1,15 @@  <?php  /**   * Elgg header logo - * The logo to display in elgg-header.   */  $site = elgg_get_site_entity();  $site_name = $site->name; +$site_url = elgg_get_site_url();  ?>  <h1> -	<a class="elgg-heading-site" href="<?php echo elgg_get_site_url(); ?>"><?php echo $site_name; ?></a> +	<a class="elgg-heading-site" href="<?php echo $site_url; ?>"> +		<?php echo $site_name; ?> +	</a>  </h1> | 
