From 0502752eb7ec0a9a61727fbdae226d54671c4fa2 Mon Sep 17 00:00:00 2001 From: Brett Profitt Date: Thu, 10 May 2012 15:54:52 -0700 Subject: Documented that results will be null if no results are returned in ElggBatch. --- engine/classes/ElggBatch.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'engine') 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 -- cgit v1.2.3 From acd2c9a08b623bda5b372942ce4c55b789b4ce56 Mon Sep 17 00:00:00 2001 From: Brett Profitt Date: Thu, 10 May 2012 16:00:08 -0700 Subject: Documented that elgg_delete_metadata/annotations() returns null for no ops. --- engine/lib/metadata.php | 9 +++++++-- engine/lib/metastrings.php | 3 ++- 2 files changed, 9 insertions(+), 3 deletions(-) (limited to 'engine') diff --git a/engine/lib/metadata.php b/engine/lib/metadata.php index 34a36d86e..973d447f5 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'); } /** @@ -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 @@ -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..0c858c9d3 100644 --- a/engine/lib/metastrings.php +++ b/engine/lib/metastrings.php @@ -716,6 +716,8 @@ 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! * + * @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 * @return mixed @@ -727,7 +729,6 @@ function elgg_batch_metastring_based_objects(array $options, $callback) { 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; -- cgit v1.2.3 From 77a8a97f7d320b03727b6d1a4b3fe6c0c2d40469 Mon Sep 17 00:00:00 2001 From: Brett Profitt Date: Thu, 10 May 2012 16:01:09 -0700 Subject: Refs #2776. Cleaned up ElggEntity::setMetaData(). --- engine/classes/ElggEntity.php | 106 +++++++++++++++++++------------------- engine/tests/objects/entities.php | 2 +- 2 files changed, 53 insertions(+), 55 deletions(-) (limited to 'engine') diff --git a/engine/classes/ElggEntity.php b/engine/classes/ElggEntity.php index dc38dafbe..6828cab1f 100644 --- a/engine/classes/ElggEntity.php +++ b/engine/classes/ElggEntity.php @@ -201,8 +201,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 +251,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 +299,70 @@ 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); + public function setMetaData($name, $value, $value_type = null, $multiple = false) { + + // 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 { + $value = 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]; + // saved entity. persist md to db. + if ($this->guid) { + if (!$this->canEditMetadata()) { + return 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; - } - } - } else { - if ($delete_first) { + // 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); - } - foreach ($value as $v) { - $result = create_metadata($this->getGUID(), $name, $v, $value_type, - $this->getOwnerGUID(), $this->getAccessId(), $multiple); - - if (!$result) { + if (false === elgg_delete_metadata($options)) { return false; } } + + // add new md + $result = true; + foreach ($value as $value_tmp) { + // at this point $value should be appended because it was cleared above if needed. + $result &= create_metadata($this->getGUID(), $name, $value_tmp, $value_type, + $this->getOwnerGUID(), $this->getAccessId(), true); + } + + return $result; } - return true; + // unsaved entity. store in temp array + 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; + } } /** 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() { -- cgit v1.2.3 From f5e638639fe8d443b88fc1a1b786c6b8fbee8fb3 Mon Sep 17 00:00:00 2001 From: Brett Profitt Date: Thu, 10 May 2012 19:09:13 -0700 Subject: Fixes #2776. Overriding permissions to delete metadata when overwriting multiple values. --- engine/classes/ElggEntity.php | 18 ++++++++--- engine/tests/api/metadata.php | 74 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 87 insertions(+), 5 deletions(-) (limited to 'engine') diff --git a/engine/classes/ElggEntity.php b/engine/classes/ElggEntity.php index 6828cab1f..164ff3838 100644 --- a/engine/classes/ElggEntity.php +++ b/engine/classes/ElggEntity.php @@ -325,10 +325,6 @@ abstract class ElggEntity extends ElggData implements // saved entity. persist md to db. if ($this->guid) { - if (!$this->canEditMetadata()) { - return false; - } - // if overwriting, delete first. if (!$multiple) { $options = array( @@ -336,23 +332,35 @@ abstract class ElggEntity extends ElggData implements 'metadata_name' => $name, 'limit' => 0 ); + // @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); } // add new md $result = true; foreach ($value as $value_tmp) { // at this point $value should be appended because it was cleared above if needed. - $result &= create_metadata($this->getGUID(), $name, $value_tmp, $value_type, + $md_id = create_metadata($this->getGUID(), $name, $value_tmp, $value_type, $this->getOwnerGUID(), $this->getAccessId(), true); + if (!$md_id) { + return false; + } } return $result; } // 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])) { diff --git a/engine/tests/api/metadata.php b/engine/tests/api/metadata.php index be8ac269c..2461e975e 100644 --- a/engine/tests/api/metadata.php +++ b/engine/tests/api/metadata.php @@ -124,6 +124,80 @@ 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' + ); + + // 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); + } + + // 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 create_metastring($string) { global $CONFIG, $METASTRINGS_CACHE, $METASTRINGS_DEADNAME_CACHE; -- cgit v1.2.3 From 25b1a1ea11182b6fc195f4cca76ec4788d79c65e Mon Sep 17 00:00:00 2001 From: Brett Profitt Date: Thu, 10 May 2012 19:45:00 -0700 Subject: Refs #4487. Turning off system log (even more) during upgrades. Removed debug call to system_log() in create_annotation(). --- engine/lib/annotations.php | 2 -- upgrade.php | 3 ++- 2 files changed, 2 insertions(+), 3 deletions(-) (limited to 'engine') diff --git a/engine/lib/annotations.php b/engine/lib/annotations.php index f32dee0f0..7383f5e04 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 diff --git a/upgrade.php b/upgrade.php index 6f7126326..963523200 100644 --- a/upgrade.php +++ b/upgrade.php @@ -20,7 +20,8 @@ define('UPGRADING', 'upgrading'); require_once(dirname(__FILE__) . "/engine/start.php"); if (get_input('upgrade') == 'upgrade') { - // disable the core system log for upgrades to avoid exceptions when the schema changes. + // disable the system log for upgrades to avoid exceptions when the schema changes. + elgg_unregister_event_handler('log', 'systemlog', 'system_log_default_logger'); elgg_unregister_event_handler('all', 'all', 'system_log_listener'); if (elgg_get_unprocessed_upgrades()) { -- cgit v1.2.3 From 1c810fd7d66e3b5121edeba1bf5bf7d118625931 Mon Sep 17 00:00:00 2001 From: Brett Profitt Date: Thu, 10 May 2012 20:09:15 -0700 Subject: Fixes #4512. Passing inc_offset only for deleting / disabling callbacks in metastring functions. --- engine/lib/annotations.php | 4 ++-- engine/lib/metadata.php | 4 ++-- engine/lib/metastrings.php | 16 ++++++++-------- 3 files changed, 12 insertions(+), 12 deletions(-) (limited to 'engine') diff --git a/engine/lib/annotations.php b/engine/lib/annotations.php index 7383f5e04..2036ccd61 100644 --- a/engine/lib/annotations.php +++ b/engine/lib/annotations.php @@ -220,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); } /** @@ -238,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/metadata.php b/engine/lib/metadata.php index 973d447f5..0ff3a43dc 100644 --- a/engine/lib/metadata.php +++ b/engine/lib/metadata.php @@ -309,7 +309,7 @@ function elgg_delete_metadata(array $options) { } $options['metastring_type'] = 'metadata'; - return elgg_batch_metastring_based_objects($options, 'elgg_batch_delete_callback'); + return elgg_batch_metastring_based_objects($options, 'elgg_batch_delete_callback', false); } /** @@ -329,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); } /** diff --git a/engine/lib/metastrings.php b/engine/lib/metastrings.php index 0c858c9d3..cf6dd4d98 100644 --- a/engine/lib/metastrings.php +++ b/engine/lib/metastrings.php @@ -718,21 +718,21 @@ function elgg_set_metastring_based_object_enabled_by_id($id, $enabled, $type) { * * @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 - * @return mixed + * @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; } - $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; } /** -- cgit v1.2.3 From f2173ecfae41c83c8200024d4b7bd6e0c7202f7a Mon Sep 17 00:00:00 2001 From: Brett Profitt Date: Mon, 14 May 2012 11:50:40 -0700 Subject: Fixes possible XSS vector. --- engine/lib/views.php | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'engine') diff --git a/engine/lib/views.php b/engine/lib/views.php index ca0ce7196..1b013be6f 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)) { -- cgit v1.2.3 From 70e5ffe5f887679b10b6c6ac8a14b1f128efbb52 Mon Sep 17 00:00:00 2001 From: Brett Profitt Date: Mon, 14 May 2012 11:59:23 -0700 Subject: Setting the useradd action's access to admin instead of public. --- CHANGES.txt | 1 + engine/lib/users.php | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) (limited to 'engine') diff --git a/CHANGES.txt b/CHANGES.txt index a7e14331d..f5cacac29 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -7,6 +7,7 @@ Version 1.8.5 Security Enhancements: * Fixed possible XSS vulnerability if using a crafted URL. + * Fixed exploit to bypass new user validation if using a crafted form. Bugfixes: * Twitter API: New users are forwarded to the correct page after creating diff --git a/engine/lib/users.php b/engine/lib/users.php index 6a881777e..e209f2c38 100644 --- a/engine/lib/users.php +++ b/engine/lib/users.php @@ -1551,7 +1551,7 @@ 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'); -- cgit v1.2.3 From 9a59aa7a3cbb0e741b9b50b6b6ce8bd021b2479a Mon Sep 17 00:00:00 2001 From: Brett Profitt Date: Mon, 14 May 2012 17:35:53 -0700 Subject: Only caching access lists after ready, system fires. This prevents a bug where access lists could be cached and not cleared during plugin boot while access was disabled, which could expose entities set to ACCESS_PRIVATE. --- CHANGES.txt | 16 +++++++++------- engine/lib/access.php | 31 +++++++++++++++++++------------ 2 files changed, 28 insertions(+), 19 deletions(-) (limited to 'engine') diff --git a/CHANGES.txt b/CHANGES.txt index f5cacac29..ae0cdc333 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -8,17 +8,19 @@ Version 1.8.5 Security Enhancements: * Fixed possible XSS vulnerability if using a crafted URL. * Fixed exploit to bypass new user validation if using a crafted form. + * Fixed incorrect caching of access lists that could allow plugins + to show private entities to non-admin and non-owning users. (Non-exploitable) Bugfixes: - * Twitter API: New users are forwarded to the correct page after creating - an account with Twitter. - * Files: PDF files are downloaded as "inline" to display in the browser. - * Fixed possible duplication errors when writing metadata with multiple values. - * Fixed possible upgrade issue if using a plugin uses the system_log hooks. - * Fixed problems when enabling more than 50 metadata or annotations. + * Twitter API: New users are forwarded to the correct page after creating + an account with Twitter. + * Files: PDF files are downloaded as "inline" to display in the browser. + * Fixed possible duplication errors when writing metadata with multiple values. + * Fixed possible upgrade issue if using a plugin uses the system_log hooks. + * Fixed problems when enabling more than 50 metadata or annotations. API: - * River entries' timestamps use elgg_view_friendly_time() and can be + * River entries' timestamps use elgg_view_friendly_time() and can be overridden with the friendly time output view. Version 1.8.4 diff --git a/engine/lib/access.php b/engine/lib/access.php index 6be252c6a..702e2c1cb 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,15 @@ 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 + if ($init_finished) { + $access_list[$user_id] = $access; + return $access_list[$user_id]; + } else { + return $access; + } } /** @@ -83,7 +89,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 +143,11 @@ 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 + if ($init_finished) { + $access_array[$user_id] = $tmp_access_array; + } } - } else { $tmp_access_array = $access_array[$user_id]; } @@ -946,7 +951,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 +1020,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'); -- cgit v1.2.3 From 11e83f1864a17a98c794dd598731a5129aa8a8e7 Mon Sep 17 00:00:00 2001 From: Brett Profitt Date: Mon, 14 May 2012 22:33:17 -0700 Subject: Making sure access calls don't get cached if access is disabled and it's the first call after $init_finished is set. --- engine/lib/access.php | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'engine') diff --git a/engine/lib/access.php b/engine/lib/access.php index 702e2c1cb..e8b3b0d52 100644 --- a/engine/lib/access.php +++ b/engine/lib/access.php @@ -51,8 +51,9 @@ function get_access_list($user_id = 0, $site_id = 0, $flush = false) { $access = "(" . implode(",", get_access_array($user_id, $site_id, $flush)) . ")"; - // only cache if done with init - if ($init_finished) { + // 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 { @@ -143,8 +144,9 @@ function get_access_array($user_id = 0, $site_id = 0, $flush = false) { $tmp_access_array[] = ACCESS_PRIVATE; } - // only cache if done with init - if ($init_finished) { + // 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; } } -- cgit v1.2.3 From 40d35166d3f2211ab76943834a983330413ab761 Mon Sep 17 00:00:00 2001 From: Brett Profitt Date: Mon, 14 May 2012 23:41:31 -0700 Subject: Refs #4313. Loading ElggPlugin classes with the fully joined objects table. This cuts the number of db queries in half for loading plugins with elgg_get_plugins(). Will look to adapt these techniques to other classes in 1.8.6. --- engine/classes/ElggPlugin.php | 62 +++++++++++++++++++++++++++++++++++++++++++ engine/lib/plugins.php | 9 ++++++- 2 files changed, 70 insertions(+), 1 deletion(-) (limited to 'engine') 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 @@ -78,6 +78,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. * diff --git a/engine/lib/plugins.php b/engine/lib/plugins.php index 123fb18d8..39a76db5d 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 ); @@ -352,7 +355,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" ); -- cgit v1.2.3 From 8da19c18b2c3faab374242dfa4ceee1ab5d6f1c2 Mon Sep 17 00:00:00 2001 From: Jeroen Dalsem Date: Tue, 15 May 2012 11:01:31 +0300 Subject: correctly registering js language. Otherwise the simple cache will not work and will constantly regenerate the cached views (which is a big issue) --- engine/lib/languages.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'engine') diff --git a/engine/lib/languages.php b/engine/lib/languages.php index bf6829a39..7a508d298 100644 --- a/engine/lib/languages.php +++ b/engine/lib/languages.php @@ -344,7 +344,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'); -- cgit v1.2.3 From 415df80c175a72cddfdc7e2266f40463353f71e8 Mon Sep 17 00:00:00 2001 From: Evan Winslow Date: Thu, 17 May 2012 08:42:57 -0700 Subject: Fixes #4249: Removes links to non-existent documentation. --- engine/classes/ElggEntity.php | 4 ---- 1 file changed, 4 deletions(-) (limited to 'engine') diff --git a/engine/classes/ElggEntity.php b/engine/classes/ElggEntity.php index 164ff3838..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) @@ -581,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) { @@ -740,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) { -- cgit v1.2.3