diff options
Diffstat (limited to 'engine')
36 files changed, 507 insertions, 236 deletions
diff --git a/engine/classes/ElggBatch.php b/engine/classes/ElggBatch.php index 0cb13eb32..c1a77a0d9 100644 --- a/engine/classes/ElggBatch.php +++ b/engine/classes/ElggBatch.php @@ -16,7 +16,7 @@   *   * Results from the callback are stored in callbackResult. If the callback   * returns only booleans, callbackResults will be the combined result of - * all calls. + * all calls. If no entities are processed, callbackResults will be null.   *   * If the callback returns anything else, callbackresult will be an indexed   * array of whatever the callback returns.  If returning error handling diff --git a/engine/classes/ElggEntity.php b/engine/classes/ElggEntity.php index dc38dafbe..77c2bbf4d 100644 --- a/engine/classes/ElggEntity.php +++ b/engine/classes/ElggEntity.php @@ -24,7 +24,6 @@   *   * @package    Elgg.Core   * @subpackage DataModel.Entities - * @link       http://docs.elgg.org/DataModel/ElggEntity   *    * @property string $type           object, user, group, or site (read-only after save)   * @property string $subtype        Further clarifies the nature of the entity (read-only after save) @@ -201,8 +200,11 @@ abstract class ElggEntity extends ElggData implements  	/**  	 * Sets the value of a property.  	 * -	 * If $name is defined in $this->attributes that value is set, otherwise it will -	 * set the appropriate item of metadata. +	 * If $name is defined in $this->attributes that value is set, otherwise it is +	 * saved as metadata. +	 * +	 * @warning Metadata set this way will inherit the entity's owner and access ID. If you want +	 * to set metadata with a different owner, use create_metadata().  	 *  	 * @warning It is important that your class populates $this->attributes with keys  	 * for all base attributes, anything not in their gets set as METADATA. @@ -248,7 +250,12 @@ abstract class ElggEntity extends ElggData implements  	public function getMetaData($name) {  		if ((int) ($this->guid) == 0) {  			if (isset($this->temp_metadata[$name])) { -				return $this->temp_metadata[$name]; +				// md is returned as an array only if more than 1 entry +				if (count($this->temp_metadata[$name]) == 1) { +					return $this->temp_metadata[$name][0]; +				} else { +					return $this->temp_metadata[$name]; +				}  			} else {  				return null;  			} @@ -291,80 +298,78 @@ abstract class ElggEntity extends ElggData implements  	/**  	 * Set a piece of metadata.  	 * -	 * @tip Plugin authors should use the magic methods. +	 * Plugin authors should use the magic methods or create_metadata(). +	 * +	 * @warning The metadata will inherit the parent entity's owner and access ID. +	 * If you want to write metadata with a different owner, use create_metadata().  	 *  	 * @access private  	 *  	 * @param string $name       Name of the metadata -	 * @param mixed  $value      Value of the metadata +	 * @param mixed  $value      Value of the metadata (doesn't support assoc arrays)  	 * @param string $value_type Types supported: integer and string. Will auto-identify if not set  	 * @param bool   $multiple   Allow multiple values for a single name (doesn't support assoc arrays)  	 *  	 * @return bool  	 */ -	public function setMetaData($name, $value, $value_type = "", $multiple = false) { -		$delete_first = false; -		// if multiple is set that always means don't delete. -		// if multiple isn't set it means override. set it to true on arrays for the foreach. -		if (!$multiple) { -			$delete_first = true; -			$multiple = is_array($value); -		} - -		if (!$this->guid) { -			// real metadata only returns as an array if there are multiple elements -			if (is_array($value) && count($value) == 1) { -				$value = $value[0]; -			} +	public function setMetaData($name, $value, $value_type = null, $multiple = false) { -			$value_is_array = is_array($value); - -			if (!isset($this->temp_metadata[$name]) || $delete_first) { -				// need to remove the indexes because real metadata doesn't have them. -				if ($value_is_array) { -					$this->temp_metadata[$name] = array_values($value); -				} else { -					$this->temp_metadata[$name] = $value; -				} -			} else { -				// multiple is always true at this point. -				// if we're setting multiple and temp isn't array, it needs to be. -				if (!is_array($this->temp_metadata[$name])) { -					$this->temp_metadata[$name] = array($this->temp_metadata[$name]); -				} - -				if ($value_is_array) { -					$this->temp_metadata[$name] = array_merge($this->temp_metadata[$name], array_values($value)); -				} else { -					$this->temp_metadata[$name][] = $value; -				} -			} +		// normalize value to an array that we will loop over +		// remove indexes if value already an array. +		if (is_array($value)) { +			$value = array_values($value);  		} else { -			if ($delete_first) { +			$value = array($value); +		} + +		// saved entity. persist md to db. +		if ($this->guid) { +			// if overwriting, delete first. +			if (!$multiple) {  				$options = array(  					'guid' => $this->getGUID(),  					'metadata_name' => $name,  					'limit' => 0  				); -				// @todo this doesn't check if it exists so we can't handle failed deletes -				// is it worth the overhead of more SQL calls to check? -				elgg_delete_metadata($options); -			} -			// save into real metadata -			if (!is_array($value)) { -				$value = array($value); +				// @todo in 1.9 make this return false if can't add metadata +				// http://trac.elgg.org/ticket/4520 +				//  +				// need to remove access restrictions right now to delete +				// because this is the expected behavior +				$ia = elgg_set_ignore_access(true); +				if (false === elgg_delete_metadata($options)) { +					return false; +				} +				elgg_set_ignore_access($ia);  			} -			foreach ($value as $v) { -				$result = create_metadata($this->getGUID(), $name, $v, $value_type, -					$this->getOwnerGUID(), $this->getAccessId(), $multiple); -				if (!$result) { +			// add new md +			$result = true; +			foreach ($value as $value_tmp) { +				// at this point $value should be appended because it was cleared above if needed. +				$md_id = create_metadata($this->getGUID(), $name, $value_tmp, $value_type, +						$this->getOwnerGUID(), $this->getAccessId(), true); +				if (!$md_id) {  					return false;  				}  			} + +			return $result;  		} -		return true; +		// unsaved entity. store in temp array +		// returning single entries instead of an array of 1 element is decided in +		// getMetaData(), just like pulling from the db. +		else { +			// if overwrite, delete first +			if (!$multiple || !isset($this->temp_metadata[$name])) { +				$this->temp_metadata[$name] = array(); +			} + +			// add new md +			$this->temp_metadata[$name] = array_merge($this->temp_metadata[$name], $value); +			return true; +		}  	}  	/** @@ -575,7 +580,6 @@ abstract class ElggEntity extends ElggData implements  	 * @param mixed  $value Value of private setting  	 *  	 * @return bool -	 * @link http://docs.elgg.org/DataModel/Entities/PrivateSettings  	 */  	function setPrivateSetting($name, $value) {  		if ((int) $this->guid > 0) { @@ -734,8 +738,6 @@ abstract class ElggEntity extends ElggData implements  	 * @param string $vartype   The type of annotation value  	 *  	 * @return bool -	 * -	 * @link http://docs.elgg.org/DataModel/Annotations  	 */  	function annotate($name, $value, $access_id = ACCESS_PRIVATE, $owner_id = 0, $vartype = "") {  		if ((int) $this->guid > 0) { diff --git a/engine/classes/ElggPlugin.php b/engine/classes/ElggPlugin.php index 33f14ae37..8c9093834 100644 --- a/engine/classes/ElggPlugin.php +++ b/engine/classes/ElggPlugin.php @@ -79,6 +79,68 @@ class ElggPlugin extends ElggObject {  	}  	/** +	 * Overridden from ElggEntity and ElggObject::load(). Core always inits plugins with +	 * a query joined to the objects_entity table, so all the info is there. +	 * +	 * @param mixed $guid GUID of an ElggObject or the stdClass object from entities table +	 * +	 * @return bool +	 * @throws InvalidClassException +	 */ +	protected function load($guid) { + +		$expected_attributes = $this->attributes; +		unset($expected_attributes['tables_split']); +		unset($expected_attributes['tables_loaded']); + +		// this was loaded with a full join +		$needs_loaded = false; + +		if ($guid instanceof stdClass) { +			$row = (array) $guid; +			$missing_attributes = array_diff_key($expected_attributes, $row); +			if ($missing_attributes) { +				$needs_loaded = true; +				$old_guid = $guid; +				$guid = $row['guid']; +			} else { +				$this->attributes = $row; +			} +		} else { +			$needs_loaded = true; +		} + +		if ($needs_loaded) { +			$entity = (array) get_entity_as_row($guid); +			$object = (array) get_object_entity_as_row($guid); + +			if (!$entity || !$object) { +				return false; +			} +			 +			$this->attributes = array_merge($this->attributes, $entity, $object); +		} + +		$this->attributes['tables_loaded'] = 2; + +		// Check the type +		if ($this->attributes['type'] != 'object') { +			$msg = elgg_echo('InvalidClassException:NotValidElggStar', array($guid, get_class())); +			throw new InvalidClassException($msg); +		} + +		// guid needs to be an int  http://trac.elgg.org/ticket/4111 +		$this->attributes['guid'] = (int)$this->attributes['guid']; + +		// cache the entity +		if ($this->attributes['guid']) { +			cache_entity($this); +		} + +		return true; +	} + +	/**  	 * Save the plugin object.  Make sure required values exist.  	 *  	 * @see ElggObject::save() diff --git a/engine/classes/ElggPluginManifest.php b/engine/classes/ElggPluginManifest.php index 7aa702d47..7e79c15c8 100644 --- a/engine/classes/ElggPluginManifest.php +++ b/engine/classes/ElggPluginManifest.php @@ -319,12 +319,26 @@ class ElggPluginManifest {  	 * @return array  	 */  	public function getCategories() { +		$bundled_plugins = array('blog', 'bookmarks', 'categories', +			'custom_index', 'dashboard', 'developers', 'diagnostics', +			'embed', 'externalpages', 'file', 'garbagecollector', +			'groups', 'htmlawed', 'invitefriends', 'likes', +			'logbrowser', 'logrotate', 'members', 'messageboard', +			'messages', 'notifications', 'oauth_api', 'pages', 'profile', +			'reportedcontent', 'search', 'tagcloud', 'thewire', 'tinymce', +			'twitter', 'twitter_api', 'uservalidationbyemail', 'zaudio', +		); +  		$cats = $this->parser->getAttribute('category');  		if (!$cats) {  			$cats = array();  		} +		if (in_array('bundled', $cats) && !in_array($this->getPluginID(), $bundled_plugins)) { +			unset($cats[array_search('bundled', $cats)]); +		} +  		return $cats;  	} diff --git a/engine/classes/ElggSite.php b/engine/classes/ElggSite.php index af3999321..e793ab9c6 100644 --- a/engine/classes/ElggSite.php +++ b/engine/classes/ElggSite.php @@ -422,6 +422,8 @@ class ElggSite extends ElggEntity {  		// default public pages  		$defaults = array( +			'walled_garden/.*', +			'login',  			'action/login',  			'register',  			'action/register', diff --git a/engine/lib/access.php b/engine/lib/access.php index 6be252c6a..e8b3b0d52 100644 --- a/engine/lib/access.php +++ b/engine/lib/access.php @@ -31,7 +31,7 @@ function get_access_list($user_id = 0, $site_id = 0, $flush = false) {  	global $CONFIG, $init_finished;  	static $access_list; -	if (!isset($access_list) || !$init_finished) { +	if (!isset($access_list)) {  		$access_list = array();  	} @@ -49,9 +49,16 @@ function get_access_list($user_id = 0, $site_id = 0, $flush = false) {  		return $access_list[$user_id];  	} -	$access_list[$user_id] = "(" . implode(",", get_access_array($user_id, $site_id, $flush)) . ")"; +	$access = "(" . implode(",", get_access_array($user_id, $site_id, $flush)) . ")"; -	return $access_list[$user_id]; +	// only cache if done with init and access is enabled (unless admin user) +	// session is loaded before init is finished, so don't need to check for user session +	if ($init_finished && (elgg_is_admin_logged_in() || !elgg_get_ignore_access())) { +		$access_list[$user_id] = $access; +		return $access_list[$user_id]; +	} else { +		return $access; +	}  }  /** @@ -83,7 +90,7 @@ function get_access_array($user_id = 0, $site_id = 0, $flush = false) {  	// this cache might be redundant. But db cache is flushed on every db write.  	static $access_array; -	if (!isset($access_array) || (!isset($init_finished)) || (!$init_finished)) { +	if (!isset($access_array)) {  		$access_array = array();  	} @@ -137,12 +144,12 @@ function get_access_array($user_id = 0, $site_id = 0, $flush = false) {  				$tmp_access_array[] = ACCESS_PRIVATE;  			} -			$access_array[$user_id] = $tmp_access_array; -		} else { -			// No user id logged in so we can only access public info -			$tmp_return = $tmp_access_array; +			// only cache if done with init and access is enabled (unless admin user) +			// session is loaded before init is finished, so don't need to check for user session +			if ($init_finished && (elgg_is_admin_logged_in() || !elgg_get_ignore_access())) { +				$access_array[$user_id] = $tmp_access_array; +			}  		} -  	} else {  		$tmp_access_array = $access_array[$user_id];  	} @@ -946,7 +953,8 @@ function elgg_get_access_object() {   *   * @global bool $init_finished   * @access private - * @todo investigate why this is needed + * @todo This is required to tell the access system to start caching because + * calls are made while in ignore access mode and before the user is logged in.   */  $init_finished = false; @@ -1014,8 +1022,9 @@ function access_test($hook, $type, $value, $params) {  	return $value;  } -// This function will let us know when 'init' has finished -elgg_register_event_handler('init', 'system', 'access_init', 9999); +// Tell the access functions the system has booted, plugins are loaded, +// and the user is logged in so it can start caching +elgg_register_event_handler('ready', 'system', 'access_init');  // For overrided permissions  elgg_register_plugin_hook_handler('permissions_check', 'all', 'elgg_override_permissions'); diff --git a/engine/lib/actions.php b/engine/lib/actions.php index c6613e6d6..3a7c02488 100644 --- a/engine/lib/actions.php +++ b/engine/lib/actions.php @@ -273,8 +273,19 @@ function validate_action_token($visibleerrors = TRUE, $token = NULL, $ts = NULL)  		} else if ($visibleerrors) {  			register_error(elgg_echo('actiongatekeeper:tokeninvalid'));  		} -	} else if ($visibleerrors) { -		register_error(elgg_echo('actiongatekeeper:missingfields')); +	} else { +		if (! empty($_SERVER['CONTENT_LENGTH']) && empty($_POST)) { +			// The size of $_POST or uploaded file has exceed the size limit +			$error_msg = elgg_trigger_plugin_hook('action_gatekeeper:upload_exceeded_msg', 'all', array( +				'post_size' => $_SERVER['CONTENT_LENGTH'], +				'visible_errors' => $visibleerrors, +			), elgg_echo('actiongatekeeper:uploadexceeded')); +		} else { +			$error_msg = elgg_echo('actiongatekeeper:missingfields'); +		} +		if ($visibleerrors) { +			register_error($error_msg); +		}  	}  	return FALSE; diff --git a/engine/lib/admin.php b/engine/lib/admin.php index 928101fc5..b65d98c95 100644 --- a/engine/lib/admin.php +++ b/engine/lib/admin.php @@ -244,6 +244,7 @@ function admin_init() {  	elgg_register_action('profile/fields/delete', '', 'admin');  	elgg_register_action('profile/fields/reorder', '', 'admin'); +	elgg_register_simplecache_view('css/admin');  	elgg_register_simplecache_view('js/admin');  	$url = elgg_get_simplecache_url('js', 'admin');  	elgg_register_js('elgg.admin', $url); @@ -571,7 +572,7 @@ function admin_markdown_page_handler($pages) {  	if (!$plugin) {  		$error = elgg_echo('admin:plugins:markdown:unknown_plugin');  		$body = elgg_view_layout('admin', array('content' => $error, 'title' => $error)); -		echo elgg_view_page($title, $body, 'admin'); +		echo elgg_view_page($error, $body, 'admin');  		return true;  	} diff --git a/engine/lib/annotations.php b/engine/lib/annotations.php index f32dee0f0..2036ccd61 100644 --- a/engine/lib/annotations.php +++ b/engine/lib/annotations.php @@ -95,8 +95,6 @@ $owner_guid = 0, $access_id = ACCESS_PRIVATE) {  	$entity = get_entity($entity_guid);  	if (elgg_trigger_event('annotate', $entity->type, $entity)) { -		system_log($entity, 'annotate'); -  		// If ok then add it  		$result = insert_data("INSERT into {$CONFIG->dbprefix}annotations  			(entity_guid, name_id, value_id, value_type, owner_guid, time_created, access_id) VALUES @@ -222,7 +220,7 @@ function elgg_delete_annotations(array $options) {  	}  	$options['metastring_type'] = 'annotations'; -	return elgg_batch_metastring_based_objects($options, 'elgg_batch_delete_callback'); +	return elgg_batch_metastring_based_objects($options, 'elgg_batch_delete_callback', false);  }  /** @@ -240,7 +238,7 @@ function elgg_disable_annotations(array $options) {  	}  	$options['metastring_type'] = 'annotations'; -	return elgg_batch_metastring_based_objects($options, 'elgg_batch_disable_callback'); +	return elgg_batch_metastring_based_objects($options, 'elgg_batch_disable_callback', false);  }  /** diff --git a/engine/lib/cache.php b/engine/lib/cache.php index c117b9ec9..be1c43e14 100644 --- a/engine/lib/cache.php +++ b/engine/lib/cache.php @@ -442,6 +442,7 @@ function _elgg_cache_init() {  	}  	if ($CONFIG->system_cache_enabled && !$CONFIG->i18n_loaded_from_cache) { +		reload_all_translations();  		foreach ($CONFIG->translations as $lang => $map) {  			elgg_save_system_cache("$lang.php", serialize($map));  		} diff --git a/engine/lib/configuration.php b/engine/lib/configuration.php index 9bf1529d6..305aa00b6 100644 --- a/engine/lib/configuration.php +++ b/engine/lib/configuration.php @@ -476,10 +476,12 @@ function get_config($name, $site_guid = 0) {  			break;  	} +	// @todo these haven't really been implemented in Elgg 1.8. Complete in 1.9.  	// show dep message  	if ($new_name) { +	//	$msg = "Config value $name has been renamed as $new_name";  		$name = $new_name; -		elgg_deprecated_notice($msg, $dep_version); +	//	elgg_deprecated_notice($msg, $dep_version);  	}  	// decide from where to return the value diff --git a/engine/lib/database.php b/engine/lib/database.php index cc2b99f6a..7d90b30b8 100644 --- a/engine/lib/database.php +++ b/engine/lib/database.php @@ -253,6 +253,10 @@ function execute_query($query, $dblink) {  		throw new DatabaseException(elgg_echo('DatabaseException:InvalidQuery'));  	} +	if (!is_resource($dblink)) { +		throw new DatabaseException(elgg_echo('DatabaseException:InvalidDBLink')); +	} +  	$dbcalls++;  	$result = mysql_query($query, $dblink); diff --git a/engine/lib/elgglib.php b/engine/lib/elgglib.php index 11bdc7285..62cb2d5bb 100644 --- a/engine/lib/elgglib.php +++ b/engine/lib/elgglib.php @@ -1053,12 +1053,14 @@ function _elgg_php_exception_handler($exception) {   *   * @return true   * @access private + * @todo Replace error_log calls with elgg_log calls.   */  function _elgg_php_error_handler($errno, $errmsg, $filename, $linenum, $vars) {  	$error = date("Y-m-d H:i:s (T)") . ": \"$errmsg\" in file $filename (line $linenum)";  	switch ($errno) {  		case E_USER_ERROR: +		case E_RECOVERABLE_ERROR: // (e.g. type hint violation)  			error_log("PHP ERROR: $error");  			register_error("ERROR: $error"); @@ -1092,8 +1094,8 @@ function _elgg_php_error_handler($errno, $errmsg, $filename, $linenum, $vars) {   *   * @note No messages will be displayed unless debugging has been enabled.   * - * @param str $message User message - * @param str $level   NOTICE | WARNING | ERROR | DEBUG + * @param string $message User message + * @param string $level   NOTICE | WARNING | ERROR | DEBUG   *   * @return bool   * @since 1.7.0 @@ -2014,15 +2016,31 @@ function elgg_is_valid_options_for_batch_operation($options, $type) {   *   * @link http://docs.elgg.org/Tutorials/WalledGarden   * @elgg_plugin_hook index system + * + * @param string $hook   The name of the hook + * @param string $type   The type of hook + * @param bool   $value  Has a plugin already rendered an index page? + * @param array  $params Array of parameters (should be empty)   * @return bool   * @access private   */ -function elgg_walled_garden_index() { +function elgg_walled_garden_index($hook, $type, $value, $params) { +	if ($value) { +		// do not create a second index page so return +		return; +	} +  	elgg_load_css('elgg.walled_garden');  	elgg_load_js('elgg.walled_garden'); -	$body = elgg_view('core/walled_garden/body'); +	$content = elgg_view('core/walled_garden/login'); +	$params = array( +		'content' => $content, +		'class' => 'elgg-walledgarden-double', +		'id' => 'elgg-walledgarden-login', +	); +	$body = elgg_view_layout('walled_garden', $params);  	echo elgg_view_page('', $body, 'walled_garden');  	// return true to prevent other plugins from adding a front page @@ -2030,6 +2048,24 @@ function elgg_walled_garden_index() {  }  /** + * Serve walled garden sections + * + * @param array $page Array of URL segments + * @return string + * @access private + */ +function _elgg_walled_garden_ajax_handler($page) { +	$view = $page[0]; +	$params = array( +		'content' => elgg_view("core/walled_garden/$view"), +		'class' => 'elgg-walledgarden-single hidden', +		'id' => str_replace('_', '-', "elgg-walledgarden-$view"), +	); +	echo elgg_view_layout('walled_garden', $params); +	return true; +} + +/**   * Checks the status of the Walled Garden and forwards to a login page   * if required.   * @@ -2049,6 +2085,8 @@ function elgg_walled_garden() {  	elgg_register_css('elgg.walled_garden', '/css/walled_garden.css');  	elgg_register_js('elgg.walled_garden', '/js/walled_garden.js'); +	elgg_register_page_handler('walled_garden', '_elgg_walled_garden_ajax_handler'); +  	// check for external page view  	if (isset($CONFIG->site) && $CONFIG->site instanceof ElggSite) {  		$CONFIG->site->checkWalledGarden(); @@ -2078,11 +2116,13 @@ function _elgg_engine_boot() {  	_elgg_load_application_config(); -	register_translations(dirname(dirname(dirname(__FILE__))) . "/languages/"); -  	_elgg_load_site_config(); +	_elgg_session_boot(); +  	_elgg_load_cache(); + +	_elgg_load_translations();  }  /** @@ -2111,6 +2151,7 @@ function elgg_init() {  	elgg_register_js('jquery.easing', 'vendors/jquery/jquery.easing.1.3.packed.js');  	elgg_register_js('elgg.avatar_cropper', 'js/lib/ui.avatar_cropper.js');  	elgg_register_js('jquery.imgareaselect', 'vendors/jquery/jquery.imgareaselect-0.9.8/scripts/jquery.imgareaselect.min.js'); +	elgg_register_js('elgg.ui.river', 'js/lib/ui.river.js');  	elgg_register_css('jquery.imgareaselect', 'vendors/jquery/jquery.imgareaselect-0.9.8/css/imgareaselect-deprecated.css'); diff --git a/engine/lib/entities.php b/engine/lib/entities.php index 4875b2c2f..abfe07276 100644 --- a/engine/lib/entities.php +++ b/engine/lib/entities.php @@ -331,7 +331,7 @@ function remove_subtype($type, $subtype) {  }  /** - * Update a registered ElggEntity type, subtype, and classname + * Update a registered ElggEntity type, subtype, and class name   *   * @param string $type    Type   * @param string $subtype Subtype @@ -340,7 +340,7 @@ function remove_subtype($type, $subtype) {   * @return bool   */  function update_subtype($type, $subtype, $class = '') { -	global $CONFIG; +	global $CONFIG, $SUBTYPE_CACHE;  	if (!$id = get_subtype_id($type, $subtype)) {  		return FALSE; @@ -348,10 +348,16 @@ function update_subtype($type, $subtype, $class = '') {  	$type = sanitise_string($type);  	$subtype = sanitise_string($subtype); -	return update_data("UPDATE {$CONFIG->dbprefix}entity_subtypes +	$result = update_data("UPDATE {$CONFIG->dbprefix}entity_subtypes  		SET type = '$type', subtype = '$subtype', class = '$class'  		WHERE id = $id  	"); + +	if ($result && isset($SUBTYPE_CACHE[$id])) { +		$SUBTYPE_CACHE[$id]->class = $class; +	} + +	return $result;  }  /** @@ -915,11 +921,11 @@ function elgg_get_entities(array $options = array()) {  	}  	if (!$options['count']) { -		if ($options['group_by'] = sanitise_string($options['group_by'])) { +		if ($options['group_by']) {  			$query .= " GROUP BY {$options['group_by']}";  		} -		if ($options['order_by'] = sanitise_string($options['order_by'])) { +		if ($options['order_by']) {  			$query .= " ORDER BY {$options['order_by']}";  		} @@ -1452,6 +1458,7 @@ function enable_entity($guid, $recursive = true) {  						'relationship' => 'disabled_with',  						'relationship_guid' => $entity->guid,  						'inverse_relationship' => true, +						'limit' => 0,  					));  					foreach ($disabled_with_it as $e) { @@ -1767,7 +1774,7 @@ function import_entity_plugin_hook($hook, $entity_type, $returnvalue, $params) {  		if ($tmp) {  			// Make sure its saved  			if (!$tmp->save()) { -				elgg_echo('ImportException:ProblemSaving', array($element->getAttribute('uuid'))); +				$msg = elgg_echo('ImportException:ProblemSaving', array($element->getAttribute('uuid')));  				throw new ImportException($msg);  			} diff --git a/engine/lib/extender.php b/engine/lib/extender.php index ffd3c1357..43421342c 100644 --- a/engine/lib/extender.php +++ b/engine/lib/extender.php @@ -105,6 +105,7 @@ function import_extender_plugin_hook($hook, $entity_type, $returnvalue, $params)  		// Save  		if (!$entity->save()) { +			$attr_name = $element->getAttribute('name');  			$msg = elgg_echo('ImportException:ProblemUpdatingMeta', array($attr_name, $entity_uuid));  			throw new ImportException($msg);  		} @@ -120,7 +121,7 @@ function import_extender_plugin_hook($hook, $entity_type, $returnvalue, $params)   * @param string $type        'metadata' or 'annotation'   * @param int    $user_guid   The GUID of the user   * - * @return true|false + * @return bool   */  function can_edit_extender($extender_id, $type, $user_guid = 0) {  	if (!elgg_is_logged_in()) { @@ -155,7 +156,7 @@ function can_edit_extender($extender_id, $type, $user_guid = 0) {  	}  	// Trigger plugin hooks -	$params = array('entity' => $entity, 'user' => $user); +	$params = array('entity' => $extender->getEntity(), 'user' => $user);  	return elgg_trigger_plugin_hook('permissions_check', $type, $params, false);  } diff --git a/engine/lib/filestore.php b/engine/lib/filestore.php index 86f6d9baa..93a127257 100644 --- a/engine/lib/filestore.php +++ b/engine/lib/filestore.php @@ -149,6 +149,12 @@ $x1 = 0, $y1 = 0, $x2 = 0, $y2 = 0, $upscale = FALSE) {  		return FALSE;  	} +	// color transparencies white (default is black) +	imagefilledrectangle( +		$new_image, 0, 0, $params['newwidth'], $params['newheight'], +		imagecolorallocate($new_image, 255, 255, 255) +	); +  	$rtn_code = imagecopyresampled(	$new_image,  									$original_image,  									0, diff --git a/engine/lib/languages.php b/engine/lib/languages.php index bf6829a39..15c48f902 100644 --- a/engine/lib/languages.php +++ b/engine/lib/languages.php @@ -8,6 +8,62 @@   */  /** + * Given a message key, returns an appropriately translated full-text string + * + * @param string $message_key The short message code + * @param array  $args        An array of arguments to pass through vsprintf(). + * @param string $language    Optionally, the standard language code + *                            (defaults to site/user default, then English) + * + * @return string Either the translated string, the English string, + * or the original language string. + */ +function elgg_echo($message_key, $args = array(), $language = "") { +	global $CONFIG; + +	static $CURRENT_LANGUAGE; + +	// old param order is deprecated +	if (!is_array($args)) { +		elgg_deprecated_notice( +			'As of Elgg 1.8, the 2nd arg to elgg_echo() is an array of string replacements and the 3rd arg is the language.', +			1.8 +		); + +		$language = $args; +		$args = array(); +	} + +	if (!isset($CONFIG->translations)) { +		// this means we probably had an exception before translations were initialized +		register_translations(dirname(dirname(dirname(__FILE__))) . "/languages/"); +	} + +	if (!$CURRENT_LANGUAGE) { +		$CURRENT_LANGUAGE = get_language(); +	} +	if (!$language) { +		$language = $CURRENT_LANGUAGE; +	} + +	if (isset($CONFIG->translations[$language][$message_key])) { +		$string = $CONFIG->translations[$language][$message_key]; +	} else if (isset($CONFIG->translations["en"][$message_key])) { +		$string = $CONFIG->translations["en"][$message_key]; +	} else { +		$string = $message_key; +	} + +	// only pass through if we have arguments to allow backward compatibility +	// with manual sprintf() calls. +	if ($args) { +		$string = vsprintf($string, $args); +	} + +	return $string; +} + +/**   * Add a translation.   *   * Translations are arrays in the Zend Translation array format, eg: @@ -82,56 +138,34 @@ function get_language() {  	return false;  } -/** - * Given a message shortcode, returns an appropriately translated full-text string - * - * @param string $message_key The short message code - * @param array  $args        An array of arguments to pass through vsprintf(). - * @param string $language    Optionally, the standard language code - *                            (defaults to site/user default, then English) - * - * @return string Either the translated string, the English string, - * or the original language string. - */ -function elgg_echo($message_key, $args = array(), $language = "") { +function _elgg_load_translations() {  	global $CONFIG; -	static $CURRENT_LANGUAGE; - -	// old param order is deprecated -	if (!is_array($args)) { -		elgg_deprecated_notice( -			'As of Elgg 1.8, the 2nd arg to elgg_echo() is an array of string replacements and the 3rd arg is the language.', -			1.8 -		); - -		$language = $args; -		$args = array(); -	} +	if ($CONFIG->system_cache_enabled) { +		$loaded = true; +		$languages = array_unique(array('en', get_current_language())); +		foreach ($languages as $language) { +			$data = elgg_load_system_cache("$language.php"); +			if ($data) { +				add_translation($language, unserialize($data)); +			} else { +				$loaded = false; +			} +		} -	if (!$CURRENT_LANGUAGE) { -		$CURRENT_LANGUAGE = get_language(); -	} -	if (!$language) { -		$language = $CURRENT_LANGUAGE; +		if ($loaded) { +			$CONFIG->i18n_loaded_from_cache = true; +			// this is here to force  +			$CONFIG->language_paths[dirname(dirname(dirname(__FILE__))) . "/languages/"] = true; +			return; +		}  	} -	if (isset($CONFIG->translations[$language][$message_key])) { -		$string = $CONFIG->translations[$language][$message_key]; -	} else if (isset($CONFIG->translations["en"][$message_key])) { -		$string = $CONFIG->translations["en"][$message_key]; -	} else { -		$string = $message_key; -	} +	// load core translations from languages directory +	register_translations(dirname(dirname(dirname(__FILE__))) . "/languages/"); +} -	// only pass through if we have arguments to allow backward compatibility -	// with manual sprintf() calls. -	if ($args) { -		$string = vsprintf($string, $args); -	} -	return $string; -}  /**   * When given a full path, finds translation files and loads them @@ -145,16 +179,9 @@ function elgg_echo($message_key, $args = array(), $language = "") {  function register_translations($path, $load_all = false) {  	global $CONFIG; -	static $load_from_cache; -	static $cache_loaded_langs; -	if (!isset($load_from_cache)) { -		$load_from_cache = $CONFIG->system_cache_enabled; -		$cache_loaded_langs = array(); -	} -  	$path = sanitise_filepath($path); -	// Make a note of this path just in case we need to register this language later +	// Make a note of this path just incase we need to register this language later  	if (!isset($CONFIG->language_paths)) {  		$CONFIG->language_paths = array();  	} @@ -162,6 +189,7 @@ function register_translations($path, $load_all = false) {  	// Get the current language based on site defaults and user preference  	$current_language = get_current_language(); +	elgg_log("Translations loaded from: $path");  	// only load these files unless $load_all is true.  	$load_language_files = array( @@ -171,32 +199,6 @@ function register_translations($path, $load_all = false) {  	$load_language_files = array_unique($load_language_files); -	if ($load_from_cache && !$load_all) { -		// load language files from cache -		$data = array(); -		foreach ($load_language_files as $lang_file) { -			$lang = substr($lang_file, 0, strpos($lang_file, '.')); -			if (!isset($cache_loaded_langs[$lang])) { -				$data[$lang] = elgg_load_system_cache($lang_file); -				if ($data[$lang]) { -					$cache_loaded_langs[$lang] = true; -				} else { -					// this language file not cached yet -					$load_from_cache = false; -				} -			} -		} - -		// are we still suppose to load from cache -		if ($load_from_cache) { -			foreach ($data as $lang => $map) { -				add_translation($lang, unserialize($map)); -			} -			$CONFIG->i18n_loaded_from_cache = true; -			return true; -		} -	} -  	$handle = opendir($path);  	if (!$handle) {  		elgg_log("Could not open language path: $path", 'ERROR'); @@ -218,11 +220,6 @@ function register_translations($path, $load_all = false) {  		}  	} -	elgg_log("Translations loaded from: $path"); - -	// make sure caching code saves language data if system cache is on -	$CONFIG->i18n_loaded_from_cache = false; -  	return $return;  } @@ -344,7 +341,7 @@ function get_missing_language_keys($language) {   */  function elgg_languages_init() {  	$lang = get_current_language(); -	elgg_register_simplecache_view("cache/js/languages/$lang"); +	elgg_register_simplecache_view("js/languages/$lang");  }  elgg_register_event_handler('init', 'system', 'elgg_languages_init'); diff --git a/engine/lib/metadata.php b/engine/lib/metadata.php index 34a36d86e..0ff3a43dc 100644 --- a/engine/lib/metadata.php +++ b/engine/lib/metadata.php @@ -297,6 +297,8 @@ function elgg_get_metadata(array $options = array()) {   *          This requires at least one constraint: metadata_owner_guid(s),   *          metadata_name(s), metadata_value(s), or guid(s) must be set.   * + * @warning This returns null on no ops. + *   * @param array $options An options array. {@see elgg_get_metadata()}   * @return mixed Null if the metadata name is invalid. Bool on success or fail.   * @since 1.8.0 @@ -307,8 +309,7 @@ function elgg_delete_metadata(array $options) {  	}  	$options['metastring_type'] = 'metadata'; -	$result = elgg_batch_metastring_based_objects($options, 'elgg_batch_delete_callback'); -	return $result; +	return elgg_batch_metastring_based_objects($options, 'elgg_batch_delete_callback', false);  }  /** @@ -316,6 +317,8 @@ function elgg_delete_metadata(array $options) {   *   * @warning Unlike elgg_get_metadata() this will not accept an empty options array!   * + * @warning This returns null on no ops. + *   * @param array $options An options array. {@See elgg_get_metadata()}   * @return mixed   * @since 1.8.0 @@ -326,7 +329,7 @@ function elgg_disable_metadata(array $options) {  	}  	$options['metastring_type'] = 'metadata'; -	return elgg_batch_metastring_based_objects($options, 'elgg_batch_disable_callback'); +	return elgg_batch_metastring_based_objects($options, 'elgg_batch_disable_callback', false);  }  /** @@ -334,6 +337,8 @@ function elgg_disable_metadata(array $options) {   *   * @warning Unlike elgg_get_metadata() this will not accept an empty options array!   * + * @warning This returns null on no ops. + *   * @param array $options An options array. {@See elgg_get_metadata()}   * @return mixed   * @since 1.8.0 diff --git a/engine/lib/metastrings.php b/engine/lib/metastrings.php index d7cc4e0bc..cf6dd4d98 100644 --- a/engine/lib/metastrings.php +++ b/engine/lib/metastrings.php @@ -716,22 +716,23 @@ function elgg_set_metastring_based_object_enabled_by_id($id, $enabled, $type) {   * @warning Unlike elgg_get_metastring_based_objects() this will not accept an   * empty options array!   * - * @param array  $options  An options array. {@See elgg_get_metastring_based_objects()} - * @param string $callback The callback to pass each result through - * @return mixed + * @warning This returns null on no ops. + * + * @param array  $options    An options array. {@See elgg_get_metastring_based_objects()} + * @param string $callback   The callback to pass each result through + * @param bool   $inc_offset Increment the offset? Pass false for callbacks that delete / disable + * + * @return bool|null true on success, false on failure, null if no objects are found.   * @since 1.8.0   * @access private   */ -function elgg_batch_metastring_based_objects(array $options, $callback) { +function elgg_batch_metastring_based_objects(array $options, $callback, $inc_offset = true) {  	if (!$options || !is_array($options)) {  		return false;  	} -	// @todo restore once ElggBatch supports callbacks that delete rows. -	$batch = new ElggBatch('elgg_get_metastring_based_objects', $options, $callback, 50, false); -	$r = $batch->callbackResult; - -	return $r; +	$batch = new ElggBatch('elgg_get_metastring_based_objects', $options, $callback, 50, $inc_offset); +	return $batch->callbackResult;  }  /** diff --git a/engine/lib/navigation.php b/engine/lib/navigation.php index a7984ce5a..4ff009bfb 100644 --- a/engine/lib/navigation.php +++ b/engine/lib/navigation.php @@ -230,7 +230,7 @@ function elgg_pop_breadcrumb() {  	global $CONFIG;  	if (is_array($CONFIG->breadcrumbs)) { -		array_pop($CONFIG->breadcrumbs); +		return array_pop($CONFIG->breadcrumbs);  	}  	return FALSE; diff --git a/engine/lib/pagehandler.php b/engine/lib/pagehandler.php index a675d976a..46c7d059e 100644 --- a/engine/lib/pagehandler.php +++ b/engine/lib/pagehandler.php @@ -129,7 +129,7 @@ function elgg_error_page_handler($hook, $type, $result, $params) {  		$content = elgg_view("errors/default", $params);  	}  	$body = elgg_view_layout('error', array('content' => $content)); -	echo elgg_view_page($title, $body, 'error'); +	echo elgg_view_page('', $body, 'error');  	exit;  } diff --git a/engine/lib/plugins.php b/engine/lib/plugins.php index 123fb18d8..d5cd4fe76 100644 --- a/engine/lib/plugins.php +++ b/engine/lib/plugins.php @@ -93,10 +93,13 @@ function elgg_get_plugin_ids_in_dir($dir = null) {  function elgg_generate_plugin_entities() {  	$site = get_config('site');  	$dir = elgg_get_plugins_path(); +	$db_prefix = elgg_get_config('dbprefix');  	$options = array(  		'type' => 'object',  		'subtype' => 'plugin', +		'selects' => array('plugin_oe.*'), +		'joins' => array("JOIN {$db_prefix}objects_entity plugin_oe on plugin_oe.guid = e.guid"),  		'limit' => ELGG_ENTITIES_NO_VALUE  	); @@ -308,6 +311,10 @@ function elgg_load_plugins() {  		$start_flags = $start_flags & ~ELGG_PLUGIN_REGISTER_VIEWS;  	} +	if (elgg_get_config('i18n_loaded_from_cache')) { +		$start_flags = $start_flags & ~ELGG_PLUGIN_REGISTER_LANGUAGES; +	} +  	$return = true;  	$plugins = elgg_get_plugins('active');  	if ($plugins) { @@ -352,7 +359,11 @@ function elgg_get_plugins($status = 'active', $site_guid = null) {  		'type' => 'object',  		'subtype' => 'plugin',  		'limit' => ELGG_ENTITIES_NO_VALUE, -		'joins' => array("JOIN {$db_prefix}private_settings ps on ps.entity_guid = e.guid"), +		'selects' => array('plugin_oe.*'), +		'joins' => array( +			"JOIN {$db_prefix}private_settings ps on ps.entity_guid = e.guid", +			"JOIN {$db_prefix}objects_entity plugin_oe on plugin_oe.guid = e.guid" +			),  		'wheres' => array("ps.name = '$priority'"),  		'order_by' => "CAST(ps.value as unsigned), e.guid"  	); diff --git a/engine/lib/relationships.php b/engine/lib/relationships.php index fabe2d2d6..f50c4a485 100644 --- a/engine/lib/relationships.php +++ b/engine/lib/relationships.php @@ -290,7 +290,7 @@ function elgg_get_entities_from_relationship($options) {  			$options['selects'] = array();  		} -		$select = array('r.*'); +		$select = array('r.id');  		$options['selects'] = array_merge($options['selects'], $select);  	} diff --git a/engine/lib/river.php b/engine/lib/river.php index 547d9495e..711832f70 100644 --- a/engine/lib/river.php +++ b/engine/lib/river.php @@ -55,7 +55,7 @@ $posted = 0, $annotation_id = 0) {  	$posted = sanitise_int($posted);  	$annotation_id = sanitise_int($annotation_id); -	$params = array( +	$values = array(  		'type' => $type,  		'subtype' => $subtype,  		'action_type' => $action_type, @@ -68,13 +68,13 @@ $posted = 0, $annotation_id = 0) {  	);  	// return false to stop insert -	$params = elgg_trigger_plugin_hook('creating', 'river', null, $params); -	if ($params == false) { +	$values = elgg_trigger_plugin_hook('creating', 'river', null, $values); +	if ($values == false) {  		// inserting did not fail - it was just prevented  		return true;  	} -	extract($params); +	extract($values);  	// Attempt to save river item; return success status  	$id = insert_data("insert into {$CONFIG->dbprefix}river " . diff --git a/engine/lib/sessions.php b/engine/lib/sessions.php index 9982d9fe8..72ca0a1c2 100644 --- a/engine/lib/sessions.php +++ b/engine/lib/sessions.php @@ -127,6 +127,10 @@ function elgg_is_admin_user($user_guid) {  /**   * Perform user authentication with a given username and password.   * + * @warning This returns an error message on failure. Use the identical operator to check + * for access: if (true === elgg_authenticate()) { ... }. + * + *   * @see login   *   * @param string $username The username @@ -372,14 +376,10 @@ function logout() {   *   * @uses $_SESSION   * - * @param string $event       Event name - * @param string $object_type Object type - * @param mixed  $object      Object - *   * @return bool   * @access private   */ -function _elgg_session_boot($event, $object_type, $object) { +function _elgg_session_boot() {  	global $DB_PREFIX, $CONFIG;  	// Use database for sessions @@ -460,9 +460,6 @@ function _elgg_session_boot($event, $object_type, $object) {  		return false;  	} -	// Since we have loaded a new user, this user may have different language preferences -	register_translations(dirname(dirname(dirname(__FILE__))) . "/languages/"); -  	return true;  } @@ -654,5 +651,3 @@ function _elgg_session_gc($maxlifetime) {  	return true;  } - -elgg_register_event_handler('boot', 'system', '_elgg_session_boot', 2); diff --git a/engine/lib/statistics.php b/engine/lib/statistics.php index e1f95ed97..5ee640549 100644 --- a/engine/lib/statistics.php +++ b/engine/lib/statistics.php @@ -95,8 +95,8 @@ function get_number_users($show_deactivated = false) {   * @return string    */  function get_online_users() { -	$count = find_active_users(600, 10, $offset, true); -	$objects = find_active_users(600, 10, $offset); +	$count = find_active_users(600, 10, 0, true); +	$objects = find_active_users(600, 10);  	if ($objects) {  		return elgg_view_entity_list($objects, array( diff --git a/engine/lib/system_log.php b/engine/lib/system_log.php index 28d90be56..53fa24557 100644 --- a/engine/lib/system_log.php +++ b/engine/lib/system_log.php @@ -156,9 +156,8 @@ function get_object_from_log_entry($entry_id) {   * This is called by the event system and should not be called directly.   *   * @param object $object The object you're talking about. - * @param string $event  String The event being logged - * - * @return mixed + * @param string $event  The event being logged + * @return void   */  function system_log($object, $event) {  	global $CONFIG; @@ -166,6 +165,12 @@ function system_log($object, $event) {  	static $cache_size = 0;  	if ($object instanceof Loggable) { + +		if (datalist_get('version') < 2012012000) { +			// this is a site that doesn't have the ip_address column yet +			return; +		} +  		// reset cache if it has grown too large  		if (!is_array($log_cache) || $cache_size > 500) {  			$log_cache = array(); @@ -213,8 +218,6 @@ function system_log($object, $event) {  			$log_cache[$time][$object_id][$event] = true;  			$cache_size += 1;  		} - -		return true;  	}  } diff --git a/engine/lib/upgrades/2012041800-1.8.3-dont_filter_passwords-c0ca4a18b38ae2bc.php b/engine/lib/upgrades/2012041800-1.8.3-dont_filter_passwords-c0ca4a18b38ae2bc.php new file mode 100644 index 000000000..b82ffbebf --- /dev/null +++ b/engine/lib/upgrades/2012041800-1.8.3-dont_filter_passwords-c0ca4a18b38ae2bc.php @@ -0,0 +1,11 @@ +<?php +/** + * Elgg 1.8.3 upgrade 2012041800 + * dont_filter_passwords + * + * Add admin notice that password handling has changed and if  + * users can't login to have them reset their passwords. + */ +elgg_add_admin_notice('dont_filter_passwords', 'Password handling has been updated to be more secure and flexible. ' +	. 'This change may prevent a small number of users from logging in with their existing passwords. ' +	. 'If a user is unable to log in, please advise him or her to reset their password, or reset it as an admin user.'); diff --git a/engine/lib/upgrades/2012041801-1.8.3-multiple_user_tokens-852225f7fd89f6c5.php b/engine/lib/upgrades/2012041801-1.8.3-multiple_user_tokens-852225f7fd89f6c5.php new file mode 100644 index 000000000..07732f261 --- /dev/null +++ b/engine/lib/upgrades/2012041801-1.8.3-multiple_user_tokens-852225f7fd89f6c5.php @@ -0,0 +1,13 @@ +<?php +/** + * Elgg 1.8.3 upgrade 2012041801 + * multiple_user_tokens + * + * Fixes http://trac.elgg.org/ticket/4291 + * Removes the unique index on users_apisessions for user_guid and site_guid + */ + +$db_prefix = elgg_get_config('dbprefix'); +$q = "ALTER TABLE {$db_prefix}users_apisessions DROP INDEX user_guid, +	ADD INDEX user_guid (user_guid, site_guid)"; +update_data($q);
\ No newline at end of file diff --git a/engine/lib/user_settings.php b/engine/lib/user_settings.php index af30d8f0d..e4069fb53 100644 --- a/engine/lib/user_settings.php +++ b/engine/lib/user_settings.php @@ -33,9 +33,9 @@ function users_settings_save() {   * @access private   */  function elgg_set_user_password() { -	$current_password = get_input('current_password'); -	$password = get_input('password'); -	$password2 = get_input('password2'); +	$current_password = get_input('current_password', null, false); +	$password = get_input('password', null, false); +	$password2 = get_input('password2', null, false);  	$user_guid = get_input('guid');  	if (!$user_guid) { diff --git a/engine/lib/users.php b/engine/lib/users.php index f1d42e25e..241b524f9 100644 --- a/engine/lib/users.php +++ b/engine/lib/users.php @@ -810,6 +810,12 @@ function validate_username($username) {  		$msg = elgg_echo('registration:usernametooshort', array($CONFIG->minusername));  		throw new RegistrationException($msg);  	} +	 +	// username in the database has a limit of 128 characters +	if (strlen($username) > 128) { +		$msg = elgg_echo('registration:usernametoolong', array(128)); +		throw new RegistrationException($msg); +	}  	// Blacklist for bad characters (partially nicked from mediawiki)  	$blacklist = '/[' . @@ -969,8 +975,8 @@ $allow_multiple_emails = false, $friend_guid = 0, $invitecode = '') {  				$friend_user->addFriend($user->guid);  				// @todo Should this be in addFriend? -				add_to_river('friends/river/create', 'friend', $user->getGUID(), $friend_guid); -				add_to_river('friends/river/create', 'friend', $friend_guid, $user->getGUID()); +				add_to_river('river/relationship/friend/create', 'friend', $user->getGUID(), $friend_guid); +				add_to_river('river/relationship/friend/create', 'friend', $friend_guid, $user->getGUID());  			}  		}  	} @@ -1551,12 +1557,12 @@ function users_init() {  	elgg_register_plugin_hook_handler('register', 'menu:user_hover', 'elgg_user_hover_menu');  	elgg_register_action('register', '', 'public'); -	elgg_register_action('useradd', '', 'public'); +	elgg_register_action('useradd', '', 'admin');  	elgg_register_action('friends/add');  	elgg_register_action('friends/remove');  	elgg_register_action('avatar/upload');  	elgg_register_action('avatar/crop'); -	elgg_register_action('avatar/revert'); +	elgg_register_action('avatar/remove');  	elgg_register_action('profile/edit');  	elgg_register_action('friends/collections/add'); diff --git a/engine/lib/views.php b/engine/lib/views.php index ca0ce7196..c98ad4e78 100644 --- a/engine/lib/views.php +++ b/engine/lib/views.php @@ -103,7 +103,10 @@ function elgg_get_viewtype() {  	$viewtype = get_input('view', NULL);  	if ($viewtype) { -		return $viewtype; +		// only word characters allowed. +		if (!preg_match('[\W]', $viewtype)) { +			return $viewtype; +		}  	}  	if (isset($CONFIG->view) && !empty($CONFIG->view)) { @@ -400,7 +403,7 @@ function elgg_view($view, $vars = array(), $bypass = false, $debug = false, $vie  	$view_orig = $view;  	// Trigger the pagesetup event -	if (!isset($CONFIG->pagesetupdone)) { +	if (!isset($CONFIG->pagesetupdone) && $CONFIG->boot_complete) {  		$CONFIG->pagesetupdone = true;  		elgg_trigger_event('pagesetup', 'system');  	} diff --git a/engine/lib/web_services.php b/engine/lib/web_services.php index 07be76ec6..da3ed76a9 100644 --- a/engine/lib/web_services.php +++ b/engine/lib/web_services.php @@ -1165,7 +1165,7 @@ function list_all_apis() {   * @access private   */  function auth_gettoken($username, $password) { -	if (elgg_authenticate($username, $password)) { +	if (true === elgg_authenticate($username, $password)) {  		$token = create_user_token($username);  		if ($token) {  			return $token; diff --git a/engine/start.php b/engine/start.php index 506e27380..5f4bded45 100644 --- a/engine/start.php +++ b/engine/start.php @@ -49,6 +49,7 @@ global $CONFIG;  if (!isset($CONFIG)) {  	$CONFIG = new stdClass;  } +$CONFIG->boot_complete = false;  $lib_dir = dirname(__FILE__) . '/lib/'; @@ -105,5 +106,7 @@ elgg_trigger_event('plugins_boot', 'system');  // Complete the boot process for both engine and plugins  elgg_trigger_event('init', 'system'); +$CONFIG->boot_complete = true; +  // System loaded and ready  elgg_trigger_event('ready', 'system'); diff --git a/engine/tests/api/metadata.php b/engine/tests/api/metadata.php index be8ac269c..244036f80 100644 --- a/engine/tests/api/metadata.php +++ b/engine/tests/api/metadata.php @@ -43,9 +43,6 @@ class ElggCoreMetadataAPITest extends ElggCoreUnitTest {  		{  			$this->assertTrue(in_array($string, $this->metastrings));  		} - -		// clean up -		$this->delete_metastrings();  	}  	public function testElggGetEntitiesFromMetadata() { @@ -77,7 +74,6 @@ class ElggCoreMetadataAPITest extends ElggCoreUnitTest {  		// clean up  		$this->object->delete(); -		$this->delete_metastrings();  	}  	public function testElggGetMetadataCount() { @@ -124,20 +120,86 @@ class ElggCoreMetadataAPITest extends ElggCoreUnitTest {  		$e->delete();  	} +	// Make sure metadata with multiple values is correctly deleted when re-written +	// by another user +	// http://trac.elgg.org/ticket/2776 +	public function test_elgg_metadata_multiple_values() { +		$u1 = new ElggUser(); +		$u1->username = rand(); +		$u1->save(); + +		$u2 = new ElggUser(); +		$u2->username = rand(); +		$u2->save(); + +		$obj = new ElggObject(); +		$obj->owner_guid = $u1->guid; +		$obj->container_guid = $u1->guid; +		$obj->access_id = ACCESS_PUBLIC; +		$obj->save(); + +		$md_values = array( +			'one', +			'two', +			'three' +		); -	protected function create_metastring($string) { -		global $CONFIG, $METASTRINGS_CACHE, $METASTRINGS_DEADNAME_CACHE; -		$METASTRINGS_CACHE = $METASTRINGS_DEADNAME_CACHE = array(); +		// need to fake different logins. +		// good times without mocking. +		$original_user = elgg_get_logged_in_user_entity(); +		$_SESSION['user'] = $u1; +		 +		elgg_set_ignore_access(false); + +		// add metadata as one user +		$obj->test = $md_values; + +		// check only these md exists +		$db_prefix = elgg_get_config('dbprefix'); +		$q = "SELECT * FROM {$db_prefix}metadata WHERE entity_guid = $obj->guid"; +		$data = get_data($q); + +		$this->assertEqual(count($md_values), count($data)); +		foreach ($data as $md_row) { +			$md = elgg_get_metadata_from_id($md_row->id); +			$this->assertTrue(in_array($md->value, $md_values)); +			$this->assertEqual('test', $md->name); +		} -		mysql_query("INSERT INTO {$CONFIG->dbprefix}metastrings (string) VALUES ('$string')"); -		$this->metastrings[$string] = mysql_insert_id(); +		// add md w/ same name as a different user +		$_SESSION['user'] = $u2; +		$md_values2 = array( +			'four', +			'five', +			'six', +			'seven' +		); + +		$obj->test = $md_values2; + +		$q = "SELECT * FROM {$db_prefix}metadata WHERE entity_guid = $obj->guid"; +		$data = get_data($q); + +		$this->assertEqual(count($md_values2), count($data)); +		foreach ($data as $md_row) { +			$md = elgg_get_metadata_from_id($md_row->id); +			$this->assertTrue(in_array($md->value, $md_values2)); +			$this->assertEqual('test', $md->name); +		} + +		$_SESSION['user'] = $original_user; + +		$obj->delete(); +		$u1->delete(); +		$u2->delete();  	} -	protected function delete_metastrings() { + +	protected function create_metastring($string) {  		global $CONFIG, $METASTRINGS_CACHE, $METASTRINGS_DEADNAME_CACHE;  		$METASTRINGS_CACHE = $METASTRINGS_DEADNAME_CACHE = array(); -		$strings = implode(', ', $this->metastrings); -		mysql_query("DELETE FROM {$CONFIG->dbprefix}metastrings WHERE id IN ($strings)"); +		mysql_query("INSERT INTO {$CONFIG->dbprefix}metastrings (string) VALUES ('$string')"); +		$this->metastrings[$string] = mysql_insert_id();  	}  } diff --git a/engine/tests/objects/entities.php b/engine/tests/objects/entities.php index a4dc7946c..248b85c9e 100644 --- a/engine/tests/objects/entities.php +++ b/engine/tests/objects/entities.php @@ -98,7 +98,7 @@ class ElggCoreEntityTest extends ElggCoreUnitTest {  		// check internal metadata array  		$metadata = $this->entity->expose_metadata(); -		$this->assertIdentical($metadata['existent'], 'testing'); +		$this->assertIdentical($metadata['existent'], array('testing'));  	}  	public function testElggEnityGetAndSetAnnotations() {  | 
