aboutsummaryrefslogtreecommitdiff
path: root/engine/classes
diff options
context:
space:
mode:
Diffstat (limited to 'engine/classes')
-rw-r--r--engine/classes/ElggAttributeLoader.php42
-rw-r--r--engine/classes/ElggAutoP.php14
-rw-r--r--engine/classes/ElggBatch.php63
-rw-r--r--engine/classes/ElggCrypto.php208
-rw-r--r--engine/classes/ElggEntity.php24
-rw-r--r--engine/classes/ElggFile.php9
-rw-r--r--engine/classes/ElggGroup.php7
-rw-r--r--engine/classes/ElggMenuBuilder.php2
-rw-r--r--engine/classes/ElggObject.php8
-rw-r--r--engine/classes/ElggPlugin.php25
-rw-r--r--engine/classes/ElggPluginPackage.php1
-rw-r--r--engine/classes/ElggUser.php9
-rw-r--r--engine/classes/ElggWidget.php7
-rw-r--r--engine/classes/ElggXMLElement.php8
14 files changed, 380 insertions, 47 deletions
diff --git a/engine/classes/ElggAttributeLoader.php b/engine/classes/ElggAttributeLoader.php
index b91e4b88a..ffc80b02d 100644
--- a/engine/classes/ElggAttributeLoader.php
+++ b/engine/classes/ElggAttributeLoader.php
@@ -4,7 +4,7 @@
* Loads ElggEntity attributes from DB or validates those passed in via constructor
*
* @access private
- *
+ *
* @package Elgg.Core
* @subpackage DataModel
*/
@@ -24,7 +24,7 @@ class ElggAttributeLoader {
'time_created',
'time_updated',
'last_action',
- 'enabled'
+ 'enabled',
);
/**
@@ -69,7 +69,7 @@ class ElggAttributeLoader {
/**
* Constructor
- *
+ *
* @param string $class class of object being loaded
* @param string $required_type entity type this is being used to populate
* @param array $initialized_attrs attributes after initializeAttributes() has been run
@@ -94,7 +94,7 @@ class ElggAttributeLoader {
/**
* Get primary attributes missing that are missing
- *
+ *
* @param stdClass $row Database row
* @return array
*/
@@ -104,7 +104,7 @@ class ElggAttributeLoader {
/**
* Get secondary attributes that are missing
- *
+ *
* @param stdClass $row Database row
* @return array
*/
@@ -114,7 +114,7 @@ class ElggAttributeLoader {
/**
* Check that the type is correct
- *
+ *
* @param stdClass $row Database row
* @return void
* @throws InvalidClassException
@@ -200,6 +200,8 @@ class ElggAttributeLoader {
// saved, these are stored w/ type "site", but with no sites_entity row. These
// are probably only created in the unit tests.
// @todo Don't save vanilla ElggEntities with type "site"
+
+ $row = $this->filterAddedColumns($row);
$row['guid'] = (int) $row['guid'];
return $row;
}
@@ -209,12 +211,38 @@ class ElggAttributeLoader {
}
}
+ $row = $this->filterAddedColumns($row);
+
// Note: If there are still missing attributes, we're running on a 1.7 or earlier schema. We let
// this pass so the upgrades can run.
- // guid needs to be an int http://trac.elgg.org/ticket/4111
+ // guid needs to be an int https://github.com/elgg/elgg/issues/4111
$row['guid'] = (int) $row['guid'];
return $row;
}
+
+ /**
+ * Filter out keys returned by the query which should not appear in the entity's attributes
+ *
+ * @param array $row All columns from the query
+ * @return array Columns acceptable for the entity's attributes
+ */
+ protected function filterAddedColumns($row) {
+ // make an array with keys as acceptable attribute names
+ $acceptable_attrs = self::$primary_attr_names;
+ array_splice($acceptable_attrs, count($acceptable_attrs), 0, $this->secondary_attr_names);
+ $acceptable_attrs = array_combine($acceptable_attrs, $acceptable_attrs);
+
+ // @todo remove these when #4584 is in place
+ $acceptable_attrs['tables_split'] = true;
+ $acceptable_attrs['tables_loaded'] = true;
+
+ foreach ($row as $key => $val) {
+ if (!isset($acceptable_attrs[$key])) {
+ unset($row[$key]);
+ }
+ }
+ return $row;
+ }
}
diff --git a/engine/classes/ElggAutoP.php b/engine/classes/ElggAutoP.php
index 71536c433..05842d1b2 100644
--- a/engine/classes/ElggAutoP.php
+++ b/engine/classes/ElggAutoP.php
@@ -110,12 +110,19 @@ class ElggAutoP {
// http://www.php.net/manual/en/domdocument.loadhtml.php#95463
libxml_use_internal_errors(true);
+ // Do not load entities. May be unnecessary, better safe than sorry
+ $disable_load_entities = libxml_disable_entity_loader(true);
+
if (!$this->_doc->loadHTML("<html><meta http-equiv='content-type' "
. "content='text/html; charset={$this->encoding}'><body>{$html}</body>"
. "</html>")) {
+
+ libxml_disable_entity_loader($disable_load_entities);
return false;
}
+ libxml_disable_entity_loader($disable_load_entities);
+
$this->_xpath = new DOMXPath($this->_doc);
// start processing recursively at the BODY element
$nodeList = $this->_xpath->query('//body[1]');
@@ -135,9 +142,16 @@ class ElggAutoP {
// re-parse so we can handle new AUTOP elements
+ // Do not load entities. May be unnecessary, better safe than sorry
+ $disable_load_entities = libxml_disable_entity_loader(true);
+
if (!$this->_doc->loadHTML($html)) {
+ libxml_disable_entity_loader($disable_load_entities);
return false;
}
+
+ libxml_disable_entity_loader($disable_load_entities);
+
// must re-create XPath object after DOM load
$this->_xpath = new DOMXPath($this->_doc);
diff --git a/engine/classes/ElggBatch.php b/engine/classes/ElggBatch.php
index eb93b0f5d..d810ea066 100644
--- a/engine/classes/ElggBatch.php
+++ b/engine/classes/ElggBatch.php
@@ -150,6 +150,20 @@ class ElggBatch
private $incrementOffset = true;
/**
+ * Entities that could not be instantiated during a fetch
+ *
+ * @var stdClass[]
+ */
+ private $incompleteEntities = array();
+
+ /**
+ * Total number of incomplete entities fetched
+ *
+ * @var int
+ */
+ private $totalIncompletes = 0;
+
+ /**
* Batches operations on any elgg_get_*() or compatible function that supports
* an options array.
*
@@ -222,6 +236,17 @@ class ElggBatch
}
/**
+ * Tell the process that an entity was incomplete during a fetch
+ *
+ * @param stdClass $row
+ *
+ * @access private
+ */
+ public function reportIncompleteEntity(stdClass $row) {
+ $this->incompleteEntities[] = $row;
+ }
+
+ /**
* Fetches the next chunk of results
*
* @return bool
@@ -260,27 +285,47 @@ class ElggBatch
if ($this->incrementOffset) {
$offset = $this->offset + $this->retrievedResults;
} else {
- $offset = $this->offset;
+ $offset = $this->offset + $this->totalIncompletes;
}
$current_options = array(
'limit' => $limit,
- 'offset' => $offset
+ 'offset' => $offset,
+ '__ElggBatch' => $this,
);
$options = array_merge($this->options, $current_options);
- $getter = $this->getter;
- if (is_string($getter)) {
- $this->results = $getter($options);
- } else {
- $this->results = call_user_func_array($getter, array($options));
+ $this->incompleteEntities = array();
+ $this->results = call_user_func_array($this->getter, array($options));
+
+ $num_results = count($this->results);
+ $num_incomplete = count($this->incompleteEntities);
+
+ $this->totalIncompletes += $num_incomplete;
+
+ if ($this->incompleteEntities) {
+ // pad the front of the results with nulls representing the incompletes
+ array_splice($this->results, 0, 0, array_pad(array(), $num_incomplete, null));
+ // ...and skip past them
+ reset($this->results);
+ for ($i = 0; $i < $num_incomplete; $i++) {
+ next($this->results);
+ }
}
if ($this->results) {
$this->chunkIndex++;
- $this->resultIndex = 0;
- $this->retrievedResults += count($this->results);
+
+ // let the system know we've jumped past the nulls
+ $this->resultIndex = $num_incomplete;
+
+ $this->retrievedResults += ($num_results + $num_incomplete);
+ if ($num_results == 0) {
+ // This fetch was *all* incompletes! We need to fetch until we can either
+ // offer at least one row to iterate over, or give up.
+ return $this->getNextResultsChunk();
+ }
return true;
} else {
return false;
diff --git a/engine/classes/ElggCrypto.php b/engine/classes/ElggCrypto.php
new file mode 100644
index 000000000..317d371e4
--- /dev/null
+++ b/engine/classes/ElggCrypto.php
@@ -0,0 +1,208 @@
+<?php
+/**
+ * ElggCrypto
+ *
+ * @package Elgg.Core
+ * @subpackage Crypto
+ *
+ * @access private
+ */
+class ElggCrypto {
+
+ /**
+ * Character set for temp passwords (no risk of embedded profanity/glyphs that look similar)
+ */
+ const CHARS_PASSWORD = 'bcdfghjklmnpqrstvwxyz2346789';
+
+ /**
+ * Generate a string of highly randomized bytes (over the full 8-bit range).
+ *
+ * @param int $length Number of bytes needed
+ * @return string Random bytes
+ *
+ * @author George Argyros <argyros.george@gmail.com>
+ * @copyright 2012, George Argyros. All rights reserved.
+ * @license Modified BSD
+ * @link https://github.com/GeorgeArgyros/Secure-random-bytes-in-PHP/blob/master/srand.php Original
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of the <organization> nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL GEORGE ARGYROS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+ public function getRandomBytes($length) {
+ /**
+ * Our primary choice for a cryptographic strong randomness function is
+ * openssl_random_pseudo_bytes.
+ */
+ $SSLstr = '4'; // http://xkcd.com/221/
+ if (function_exists('openssl_random_pseudo_bytes')
+ && (version_compare(PHP_VERSION, '5.3.4') >= 0 || substr(PHP_OS, 0, 3) !== 'WIN')) {
+ $SSLstr = openssl_random_pseudo_bytes($length, $strong);
+ if ($strong) {
+ return $SSLstr;
+ }
+ }
+
+ /**
+ * If mcrypt extension is available then we use it to gather entropy from
+ * the operating system's PRNG. This is better than reading /dev/urandom
+ * directly since it avoids reading larger blocks of data than needed.
+ * Older versions of mcrypt_create_iv may be broken or take too much time
+ * to finish so we only use this function with PHP 5.3.7 and above.
+ * @see https://bugs.php.net/bug.php?id=55169
+ */
+ if (function_exists('mcrypt_create_iv')
+ && (version_compare(PHP_VERSION, '5.3.7') >= 0 || substr(PHP_OS, 0, 3) !== 'WIN')) {
+ $str = mcrypt_create_iv($length, MCRYPT_DEV_URANDOM);
+ if ($str !== false) {
+ return $str;
+ }
+ }
+
+ /**
+ * No build-in crypto randomness function found. We collect any entropy
+ * available in the PHP core PRNGs along with some filesystem info and memory
+ * stats. To make this data cryptographically strong we add data either from
+ * /dev/urandom or if its unavailable, we gather entropy by measuring the
+ * time needed to compute a number of SHA-1 hashes.
+ */
+ $str = '';
+ $bits_per_round = 2; // bits of entropy collected in each clock drift round
+ $msec_per_round = 400; // expected running time of each round in microseconds
+ $hash_len = 20; // SHA-1 Hash length
+ $total = $length; // total bytes of entropy to collect
+
+ $handle = @fopen('/dev/urandom', 'rb');
+ if ($handle && function_exists('stream_set_read_buffer')) {
+ @stream_set_read_buffer($handle, 0);
+ }
+
+ do {
+ $bytes = ($total > $hash_len) ? $hash_len : $total;
+ $total -= $bytes;
+
+ //collect any entropy available from the PHP system and filesystem
+ $entropy = rand() . uniqid(mt_rand(), true) . $SSLstr;
+ $entropy .= implode('', @fstat(@fopen(__FILE__, 'r')));
+ $entropy .= memory_get_usage() . getmypid();
+ $entropy .= serialize($_ENV) . serialize($_SERVER);
+ if (function_exists('posix_times')) {
+ $entropy .= serialize(posix_times());
+ }
+ if (function_exists('zend_thread_id')) {
+ $entropy .= zend_thread_id();
+ }
+
+ if ($handle) {
+ $entropy .= @fread($handle, $bytes);
+ } else {
+ // Measure the time that the operations will take on average
+ for ($i = 0; $i < 3; $i++) {
+ $c1 = microtime(true);
+ $var = sha1(mt_rand());
+ for ($j = 0; $j < 50; $j++) {
+ $var = sha1($var);
+ }
+ $c2 = microtime(true);
+ $entropy .= $c1 . $c2;
+ }
+
+ // Based on the above measurement determine the total rounds
+ // in order to bound the total running time.
+ $rounds = (int) ($msec_per_round * 50 / (int) (($c2 - $c1) * 1000000));
+
+ // Take the additional measurements. On average we can expect
+ // at least $bits_per_round bits of entropy from each measurement.
+ $iter = $bytes * (int) (ceil(8 / $bits_per_round));
+
+ for ($i = 0; $i < $iter; $i++) {
+ $c1 = microtime();
+ $var = sha1(mt_rand());
+ for ($j = 0; $j < $rounds; $j++) {
+ $var = sha1($var);
+ }
+ $c2 = microtime();
+ $entropy .= $c1 . $c2;
+ }
+ }
+
+ // We assume sha1 is a deterministic extractor for the $entropy variable.
+ $str .= sha1($entropy, true);
+
+ } while ($length > strlen($str));
+
+ if ($handle) {
+ @fclose($handle);
+ }
+
+ return substr($str, 0, $length);
+ }
+
+ /**
+ * Generate a random string of specified length.
+ *
+ * Uses supplied character list for generating the new string.
+ * If no character list provided - uses Base64 URL character set.
+ *
+ * @param int $length Desired length of the string
+ * @param string|null $chars Characters to be chosen from randomly. If not given, the Base64 URL
+ * charset will be used.
+ *
+ * @return string The random string
+ *
+ * @throws InvalidArgumentException
+ *
+ * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license http://framework.zend.com/license/new-bsd New BSD License
+ *
+ * @see https://github.com/zendframework/zf2/blob/master/library/Zend/Math/Rand.php#L179
+ */
+ public static function getRandomString($length, $chars = null) {
+ if ($length < 1) {
+ throw new InvalidArgumentException('Length should be >= 1');
+ }
+
+ if (empty($chars)) {
+ $numBytes = ceil($length * 0.75);
+ $bytes = self::getRandomBytes($numBytes);
+ $string = substr(rtrim(base64_encode($bytes), '='), 0, $length);
+
+ // Base64 URL
+ return strtr($string, '+/', '-_');
+ }
+
+ $listLen = strlen($chars);
+
+ if ($listLen == 1) {
+ return str_repeat($chars, $length);
+ }
+
+ $bytes = self::getRandomBytes($length);
+ $pos = 0;
+ $result = '';
+ for ($i = 0; $i < $length; $i++) {
+ $pos = ($pos + ord($bytes[$i])) % $listLen;
+ $result .= $chars[$pos];
+ }
+
+ return $result;
+ }
+}
diff --git a/engine/classes/ElggEntity.php b/engine/classes/ElggEntity.php
index 8b3ceb551..a563f6fad 100644
--- a/engine/classes/ElggEntity.php
+++ b/engine/classes/ElggEntity.php
@@ -24,7 +24,7 @@
*
* @package Elgg.Core
* @subpackage DataModel.Entities
- *
+ *
* @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)
* @property int $guid The unique identifier for this entity (read only)
@@ -352,8 +352,8 @@ abstract class ElggEntity extends ElggData implements
'limit' => 0
);
// @todo in 1.9 make this return false if can't add metadata
- // http://trac.elgg.org/ticket/4520
- //
+ // https://github.com/elgg/elgg/issues/4520
+ //
// need to remove access restrictions right now to delete
// because this is the expected behavior
$ia = elgg_set_ignore_access(true);
@@ -379,7 +379,7 @@ abstract class ElggEntity extends ElggData implements
// 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.
- //
+ //
// if overwrite, delete first
if (!$multiple || !isset($this->temp_metadata[$name])) {
$this->temp_metadata[$name] = array();
@@ -964,7 +964,7 @@ abstract class ElggEntity extends ElggData implements
*
* @tip Can be overridden by registering for the permissions_check:comment,
* <entity type> plugin hook.
- *
+ *
* @param int $user_guid User guid (default is logged in user)
*
* @return bool
@@ -1270,15 +1270,23 @@ abstract class ElggEntity extends ElggData implements
public function save() {
$guid = $this->getGUID();
if ($guid > 0) {
- _elgg_cache_entity($this);
- return update_entity(
+ // See #5600. This ensures the lower level can_edit_entity() check will use a
+ // fresh entity from the DB so it sees the persisted owner_guid
+ _elgg_disable_caching_for_entity($guid);
+
+ $ret = update_entity(
$guid,
$this->get('owner_guid'),
$this->get('access_id'),
$this->get('container_guid'),
$this->get('time_created')
);
+
+ _elgg_enable_caching_for_entity($guid);
+ _elgg_cache_entity($this);
+
+ return $ret;
} else {
// Create a new entity (nb: using attribute array directly
// 'cos set function does something special!)
@@ -1357,7 +1365,7 @@ abstract class ElggEntity extends ElggData implements
$this->attributes['tables_loaded']++;
}
- // guid needs to be an int http://trac.elgg.org/ticket/4111
+ // guid needs to be an int https://github.com/elgg/elgg/issues/4111
$this->attributes['guid'] = (int)$this->attributes['guid'];
// Cache object handle
diff --git a/engine/classes/ElggFile.php b/engine/classes/ElggFile.php
index 3e9c24c17..23080834b 100644
--- a/engine/classes/ElggFile.php
+++ b/engine/classes/ElggFile.php
@@ -275,9 +275,14 @@ class ElggFile extends ElggObject {
*/
public function delete() {
$fs = $this->getFilestore();
- if ($fs->delete($this)) {
- return parent::delete();
+
+ $result = $fs->delete($this);
+
+ if ($this->getGUID() && $result) {
+ $result = parent::delete();
}
+
+ return $result;
}
/**
diff --git a/engine/classes/ElggGroup.php b/engine/classes/ElggGroup.php
index 61f9163d5..7e69b7a84 100644
--- a/engine/classes/ElggGroup.php
+++ b/engine/classes/ElggGroup.php
@@ -352,7 +352,12 @@ class ElggGroup extends ElggEntity
}
// Now save specific stuff
- return create_group_entity($this->get('guid'), $this->get('name'), $this->get('description'));
+
+ _elgg_disable_caching_for_entity($this->guid);
+ $ret = create_group_entity($this->get('guid'), $this->get('name'), $this->get('description'));
+ _elgg_enable_caching_for_entity($this->guid);
+
+ return $ret;
}
// EXPORTABLE INTERFACE ////////////////////////////////////////////////////////////
diff --git a/engine/classes/ElggMenuBuilder.php b/engine/classes/ElggMenuBuilder.php
index 276cb6b2c..b463143d8 100644
--- a/engine/classes/ElggMenuBuilder.php
+++ b/engine/classes/ElggMenuBuilder.php
@@ -165,7 +165,7 @@ class ElggMenuBuilder {
// scan looking for a selected item
foreach ($this->menu as $menu_item) {
if ($menu_item->getHref()) {
- if (elgg_http_url_is_identical(full_url(), $menu_item->getHref())) {
+ if (elgg_http_url_is_identical(current_page_url(), $menu_item->getHref())) {
$menu_item->setSelected(true);
return $menu_item;
}
diff --git a/engine/classes/ElggObject.php b/engine/classes/ElggObject.php
index d54752dca..aeaa3ba5c 100644
--- a/engine/classes/ElggObject.php
+++ b/engine/classes/ElggObject.php
@@ -126,8 +126,12 @@ class ElggObject extends ElggEntity {
}
// Save ElggObject-specific attributes
- return create_object_entity($this->get('guid'), $this->get('title'),
- $this->get('description'));
+
+ _elgg_disable_caching_for_entity($this->guid);
+ $ret = create_object_entity($this->get('guid'), $this->get('title'), $this->get('description'));
+ _elgg_enable_caching_for_entity($this->guid);
+
+ return $ret;
}
/**
diff --git a/engine/classes/ElggPlugin.php b/engine/classes/ElggPlugin.php
index c1c46f272..545b9a53c 100644
--- a/engine/classes/ElggPlugin.php
+++ b/engine/classes/ElggPlugin.php
@@ -299,17 +299,15 @@ class ElggPlugin extends ElggObject {
$private_settings = get_data($q);
- if ($private_settings) {
- $return = array();
+ $return = array();
+ if ($private_settings) {
foreach ($private_settings as $setting) {
$return[$setting->name] = $setting->value;
}
-
- return $return;
}
- return false;
+ return $return;
}
/**
@@ -350,11 +348,14 @@ class ElggPlugin extends ElggObject {
*/
public function unsetAllSettings() {
$db_prefix = get_config('dbprefix');
- $ps_prefix = elgg_namespace_plugin_private_setting('setting', '');
+
+ $us_prefix = elgg_namespace_plugin_private_setting('user_setting', '', $this->getID());
+ $is_prefix = elgg_namespace_plugin_private_setting('internal', '', $this->getID());
$q = "DELETE FROM {$db_prefix}private_settings
WHERE entity_guid = $this->guid
- AND name NOT LIKE '$ps_prefix%'";
+ AND name NOT LIKE '$us_prefix%'
+ AND name NOT LIKE '$is_prefix%'";
return delete_data($q);
}
@@ -420,20 +421,18 @@ class ElggPlugin extends ElggObject {
$private_settings = get_data($q);
- if ($private_settings) {
- $return = array();
+ $return = array();
+ if ($private_settings) {
foreach ($private_settings as $setting) {
$name = substr($setting->name, $ps_prefix_len);
$value = $setting->value;
$return[$name] = $value;
}
-
- return $return;
}
- return false;
+ return $return;
}
/**
@@ -546,7 +545,7 @@ class ElggPlugin extends ElggObject {
* Returns if the plugin is complete, meaning has all required files
* and Elgg can read them and they make sense.
*
- * @todo bad name? This could be confused with isValid() from ElggPackage.
+ * @todo bad name? This could be confused with isValid() from ElggPluginPackage.
*
* @return bool
*/
diff --git a/engine/classes/ElggPluginPackage.php b/engine/classes/ElggPluginPackage.php
index 209242288..37eb4bf4d 100644
--- a/engine/classes/ElggPluginPackage.php
+++ b/engine/classes/ElggPluginPackage.php
@@ -294,6 +294,7 @@ class ElggPluginPackage {
return true;
}
+ $this->errorMsg = elgg_echo('unknown_error');
return false;
}
diff --git a/engine/classes/ElggUser.php b/engine/classes/ElggUser.php
index 6d9f10b57..6163f9b62 100644
--- a/engine/classes/ElggUser.php
+++ b/engine/classes/ElggUser.php
@@ -40,6 +40,9 @@ class ElggUser extends ElggEntity
$this->attributes['code'] = NULL;
$this->attributes['banned'] = "no";
$this->attributes['admin'] = 'no';
+ $this->attributes['prev_last_action'] = NULL;
+ $this->attributes['last_login'] = NULL;
+ $this->attributes['prev_last_login'] = NULL;
$this->attributes['tables_split'] = 2;
}
@@ -129,9 +132,13 @@ class ElggUser extends ElggEntity
}
// Now save specific stuff
- return create_user_entity($this->get('guid'), $this->get('name'), $this->get('username'),
+ _elgg_disable_caching_for_entity($this->guid);
+ $ret = create_user_entity($this->get('guid'), $this->get('name'), $this->get('username'),
$this->get('password'), $this->get('salt'), $this->get('email'), $this->get('language'),
$this->get('code'));
+ _elgg_enable_caching_for_entity($this->guid);
+
+ return $ret;
}
/**
diff --git a/engine/classes/ElggWidget.php b/engine/classes/ElggWidget.php
index c123e5032..66191bf47 100644
--- a/engine/classes/ElggWidget.php
+++ b/engine/classes/ElggWidget.php
@@ -146,10 +146,15 @@ class ElggWidget extends ElggObject {
}
}
+ $bottom_rank = count($widgets);
+ if ($column == $this->column) {
+ $bottom_rank--;
+ }
+
if ($rank == 0) {
// top of the column
$this->order = reset($widgets)->order - 10;
- } elseif ($rank == (count($widgets) - 1)) {
+ } elseif ($rank == $bottom_rank) {
// bottom of the column of active widgets
$this->order = end($widgets)->order + 10;
} else {
diff --git a/engine/classes/ElggXMLElement.php b/engine/classes/ElggXMLElement.php
index 6f2633e25..cbd3fc5ce 100644
--- a/engine/classes/ElggXMLElement.php
+++ b/engine/classes/ElggXMLElement.php
@@ -20,7 +20,12 @@ class ElggXMLElement {
if ($xml instanceof SimpleXMLElement) {
$this->_element = $xml;
} else {
+ // do not load entities
+ $disable_load_entities = libxml_disable_entity_loader(true);
+
$this->_element = new SimpleXMLElement($xml);
+
+ libxml_disable_entity_loader($disable_load_entities);
}
}
@@ -123,5 +128,4 @@ class ElggXMLElement {
}
return false;
}
-
-} \ No newline at end of file
+}