aboutsummaryrefslogtreecommitdiff
path: root/engine/lib
diff options
context:
space:
mode:
Diffstat (limited to 'engine/lib')
-rw-r--r--engine/lib/actions.php27
-rw-r--r--engine/lib/admin.php8
-rw-r--r--engine/lib/annotations.php40
-rw-r--r--engine/lib/database.php12
-rw-r--r--engine/lib/deprecated-1.7.php2
-rw-r--r--engine/lib/deprecated-1.8.php2
-rw-r--r--engine/lib/deprecated-1.9.php582
-rw-r--r--engine/lib/elgglib.php7
-rw-r--r--engine/lib/entities.php107
-rw-r--r--engine/lib/extender.php18
-rw-r--r--engine/lib/group.php1
-rw-r--r--engine/lib/input.php4
-rw-r--r--engine/lib/memcache.php20
-rw-r--r--engine/lib/metadata.php33
-rw-r--r--engine/lib/metastrings.php21
-rw-r--r--engine/lib/navigation.php9
-rw-r--r--engine/lib/notification.php15
-rw-r--r--engine/lib/output.php27
-rw-r--r--engine/lib/plugins.php47
-rw-r--r--engine/lib/river.php10
-rw-r--r--engine/lib/sessions.php9
-rw-r--r--engine/lib/statistics.php10
-rw-r--r--engine/lib/system_log.php11
-rw-r--r--engine/lib/upgrade.php2
-rw-r--r--engine/lib/upgrades/2010033101.php2
-rw-r--r--engine/lib/upgrades/2012041801-1.8.3-multiple_user_tokens-852225f7fd89f6c5.php2
-rw-r--r--engine/lib/upgrades/2013051700-1.8.15-add_missing_group_index-52a63a3a3ffaced2.php28
-rw-r--r--engine/lib/upgrades/2013052900-1.8.15-ipv6_in_syslog-f5c2cc0196e9e731.php12
-rw-r--r--engine/lib/upgrades/2013060900-1.8.15-site_secret-404fc165cf9e0ac9.php16
-rw-r--r--engine/lib/users.php6
-rw-r--r--engine/lib/views.php30
-rw-r--r--engine/lib/web_services.php13
32 files changed, 1028 insertions, 105 deletions
diff --git a/engine/lib/actions.php b/engine/lib/actions.php
index 56936f582..8047914ac 100644
--- a/engine/lib/actions.php
+++ b/engine/lib/actions.php
@@ -364,16 +364,19 @@ function generate_action_token($timestamp) {
}
/**
- * Initialise the site secret hash.
+ * Initialise the site secret (32 bytes: "z" to indicate format + 186-bit key in Base64 URL).
*
* Used during installation and saves as a datalist.
*
+ * Note: Old secrets were hex encoded.
+ *
* @return mixed The site secret hash or false
* @access private
* @todo Move to better file.
*/
function init_site_secret() {
- $secret = md5(rand() . microtime());
+ $secret = 'z' . ElggCrypto::getRandomString(31);
+
if (datalist_set('__site_secret__', $secret)) {
return $secret;
}
@@ -400,6 +403,26 @@ function get_site_secret() {
}
/**
+ * Get the strength of the site secret
+ *
+ * @return string "strong", "moderate", or "weak"
+ * @access private
+ */
+function _elgg_get_site_secret_strength() {
+ $secret = get_site_secret();
+ if ($secret[0] !== 'z') {
+ $rand_max = getrandmax();
+ if ($rand_max < pow(2, 16)) {
+ return 'weak';
+ }
+ if ($rand_max < pow(2, 32)) {
+ return 'moderate';
+ }
+ }
+ return 'strong';
+}
+
+/**
* Check if an action is registered and its script exists.
*
* @param string $action Action name
diff --git a/engine/lib/admin.php b/engine/lib/admin.php
index 243cdef46..f36f29668 100644
--- a/engine/lib/admin.php
+++ b/engine/lib/admin.php
@@ -134,11 +134,11 @@ function elgg_delete_admin_notice($id) {
}
/**
- * List all admin messages.
+ * Get admin notices. An admin must be logged in since the notices are private.
*
* @param int $limit Limit
*
- * @return array List of admin notices
+ * @return array Array of admin notices
* @since 1.8.0
*/
function elgg_get_admin_notices($limit = 10) {
@@ -158,11 +158,13 @@ function elgg_get_admin_notices($limit = 10) {
* @since 1.8.0
*/
function elgg_admin_notice_exists($id) {
+ $old_ia = elgg_set_ignore_access(true);
$notice = elgg_get_entities_from_metadata(array(
'type' => 'object',
'subtype' => 'admin_notice',
'metadata_name_value_pair' => array('name' => 'admin_notice_id', 'value' => $id)
));
+ elgg_set_ignore_access($old_ia);
return ($notice) ? TRUE : FALSE;
}
@@ -234,6 +236,7 @@ function admin_init() {
elgg_register_action('admin/site/update_advanced', '', 'admin');
elgg_register_action('admin/site/flush_cache', '', 'admin');
elgg_register_action('admin/site/unlock_upgrade', '', 'admin');
+ elgg_register_action('admin/site/regenerate_secret', '', 'admin');
elgg_register_action('admin/menu/save', '', 'admin');
@@ -289,6 +292,7 @@ function admin_init() {
elgg_register_admin_menu_item('configure', 'settings', null, 100);
elgg_register_admin_menu_item('configure', 'basic', 'settings', 10);
elgg_register_admin_menu_item('configure', 'advanced', 'settings', 20);
+ elgg_register_admin_menu_item('configure', 'advanced/site_secret', 'settings', 25);
elgg_register_admin_menu_item('configure', 'menu_items', 'appearance', 30);
elgg_register_admin_menu_item('configure', 'profile_fields', 'appearance', 40);
// default widgets is added via an event handler elgg_default_widgets_init() in widgets.php
diff --git a/engine/lib/annotations.php b/engine/lib/annotations.php
index bd5ea1a1f..5e9b530de 100644
--- a/engine/lib/annotations.php
+++ b/engine/lib/annotations.php
@@ -224,7 +224,7 @@ function elgg_get_annotations(array $options = array()) {
* annotation_name(s), annotation_value(s), or guid(s) must be set.
*
* @param array $options An options array. {@See elgg_get_annotations()}
- * @return mixed Null if the metadata name is invalid. Bool on success or fail.
+ * @return bool|null true on success, false on failure, null if no annotations to delete.
* @since 1.8.0
*/
function elgg_delete_annotations(array $options) {
@@ -242,16 +242,20 @@ function elgg_delete_annotations(array $options) {
* @warning Unlike elgg_get_annotations() this will not accept an empty options array!
*
* @param array $options An options array. {@See elgg_get_annotations()}
- * @return mixed
+ * @return bool|null true on success, false on failure, null if no annotations disabled.
* @since 1.8.0
*/
function elgg_disable_annotations(array $options) {
if (!elgg_is_valid_options_for_batch_operation($options, 'annotations')) {
return false;
}
+
+ // if we can see hidden (disabled) we need to use the offset
+ // otherwise we risk an infinite loop if there are more than 50
+ $inc_offset = access_get_show_hidden_status();
$options['metastring_type'] = 'annotations';
- return elgg_batch_metastring_based_objects($options, 'elgg_batch_disable_callback', false);
+ return elgg_batch_metastring_based_objects($options, 'elgg_batch_disable_callback', $inc_offset);
}
/**
@@ -259,8 +263,11 @@ function elgg_disable_annotations(array $options) {
*
* @warning Unlike elgg_get_annotations() this will not accept an empty options array!
*
+ * @warning In order to enable annotations, you must first use
+ * {@link access_show_hidden_entities()}.
+ *
* @param array $options An options array. {@See elgg_get_annotations()}
- * @return mixed
+ * @return bool|null true on success, false on failure, null if no metadata enabled.
* @since 1.8.0
*/
function elgg_enable_annotations(array $options) {
@@ -416,8 +423,8 @@ function elgg_list_entities_from_annotations($options = array()) {
function elgg_get_entities_from_annotation_calculation($options) {
$db_prefix = elgg_get_config('dbprefix');
$defaults = array(
- 'calculation' => 'sum',
- 'order_by' => 'annotation_calculation desc'
+ 'calculation' => 'sum',
+ 'order_by' => 'annotation_calculation desc'
);
$options = array_merge($defaults, $options);
@@ -454,6 +461,12 @@ function elgg_get_entities_from_annotation_calculation($options) {
* @return string
*/
function elgg_list_entities_from_annotation_calculation($options) {
+ $defaults = array(
+ 'calculation' => 'sum',
+ 'order_by' => 'annotation_calculation desc'
+ );
+ $options = array_merge($defaults, $options);
+
return elgg_list_entities($options, 'elgg_get_entities_from_annotation_calculation');
}
@@ -532,15 +545,16 @@ function elgg_annotation_exists($entity_guid, $annotation_type, $owner_guid = NU
return FALSE;
}
- $entity_guid = (int)$entity_guid;
- $annotation_type = sanitise_string($annotation_type);
+ $entity_guid = sanitize_int($entity_guid);
+ $owner_guid = sanitize_int($owner_guid);
+ $annotation_type = sanitize_string($annotation_type);
- $sql = "select a.id" .
- " FROM {$CONFIG->dbprefix}annotations a, {$CONFIG->dbprefix}metastrings m " .
- " WHERE a.owner_guid={$owner_guid} AND a.entity_guid={$entity_guid} " .
- " AND a.name_id=m.id AND m.string='{$annotation_type}'";
+ $sql = "SELECT a.id FROM {$CONFIG->dbprefix}annotations a" .
+ " JOIN {$CONFIG->dbprefix}metastrings m ON a.name_id = m.id" .
+ " WHERE a.owner_guid = $owner_guid AND a.entity_guid = $entity_guid" .
+ " AND m.string = '$annotation_type'";
- if ($check_annotation = get_data_row($sql)) {
+ if (get_data_row($sql)) {
return TRUE;
}
diff --git a/engine/lib/database.php b/engine/lib/database.php
index 37dfb8f8d..a7949788d 100644
--- a/engine/lib/database.php
+++ b/engine/lib/database.php
@@ -129,7 +129,7 @@ function establish_db_link($dblinkname = "readwrite") {
// Set up cache if global not initialized and query cache not turned off
if ((!$DB_QUERY_CACHE) && (!$db_cache_off)) {
// @todo if we keep this cache in 1.9, expose the size as a config parameter
- $DB_QUERY_CACHE = new ElggLRUCache(200);
+ $DB_QUERY_CACHE = new ElggLRUCache(200);
}
}
@@ -399,14 +399,14 @@ function elgg_query_runner($query, $callback = null, $single = false) {
// Since we want to cache results of running the callback, we need to
// need to namespace the query with the callback and single result request.
- // http://trac.elgg.org/ticket/4049
+ // https://github.com/elgg/elgg/issues/4049
$hash = (string)$callback . (int)$single . $query;
// Is cached?
if ($DB_QUERY_CACHE) {
if (isset($DB_QUERY_CACHE[$hash])) {
elgg_log("DB query $query results returned from cache (hash: $hash)", 'NOTICE');
- return $DB_QUERY_CACHE[$hash];
+ return $DB_QUERY_CACHE[$hash];
}
}
@@ -524,7 +524,7 @@ function delete_data($query) {
/**
* Invalidate the query cache
- *
+ *
* @access private
*/
function _elgg_invalidate_query_cache() {
@@ -533,7 +533,7 @@ function _elgg_invalidate_query_cache() {
$DB_QUERY_CACHE->clear();
elgg_log("Query cache invalidated", 'NOTICE');
} elseif ($DB_QUERY_CACHE) {
- // In case someone sets the cache to an array and primes it with data
+ // In case someone sets the cache to an array and primes it with data
$DB_QUERY_CACHE = array();
elgg_log("Query cache invalidated", 'NOTICE');
}
@@ -668,7 +668,7 @@ function run_sql_script($scriptlocation) {
/**
* Format a query string for logging
- *
+ *
* @param string $query Query string
* @return string
* @access private
diff --git a/engine/lib/deprecated-1.7.php b/engine/lib/deprecated-1.7.php
index 519eea89d..ee95b5611 100644
--- a/engine/lib/deprecated-1.7.php
+++ b/engine/lib/deprecated-1.7.php
@@ -1137,6 +1137,7 @@ function make_register_object($register_name, $register_value, $children_array =
* @param int $guid GUID
*
* @return 1
+ * @deprecated 1.7
*/
function delete_object_entity($guid) {
system_message(elgg_echo('deprecatedfunction', array('delete_user_entity')));
@@ -1154,6 +1155,7 @@ function delete_object_entity($guid) {
* @param int $guid User GUID
*
* @return 1
+ * @deprecated 1.7
*/
function delete_user_entity($guid) {
system_message(elgg_echo('deprecatedfunction', array('delete_user_entity')));
diff --git a/engine/lib/deprecated-1.8.php b/engine/lib/deprecated-1.8.php
index 6aa42a81d..91068d047 100644
--- a/engine/lib/deprecated-1.8.php
+++ b/engine/lib/deprecated-1.8.php
@@ -3414,6 +3414,7 @@ function list_annotations($entity_guid, $name = "", $limit = 25, $asc = true) {
* @param unknown_type $timeupper
* @param unknown_type $calculation
* @internal Don't use this at all.
+ * @deprecated 1.8 Use elgg_get_annotations()
*/
function elgg_deprecated_annotation_calculation($entity_guid = 0, $entity_type = "", $entity_subtype = "",
$name = "", $value = "", $value_type = "", $owner_guid = 0, $timelower = 0,
@@ -4667,6 +4668,7 @@ function display_widget(ElggObject $widget) {
*
* @param ElggEntity $entity
* @return int Number of comments
+ * @deprecated 1.8 Use ElggEntity->countComments()
*/
function elgg_count_comments($entity) {
elgg_deprecated_notice('elgg_count_comments() is deprecated by ElggEntity->countComments()', 1.8);
diff --git a/engine/lib/deprecated-1.9.php b/engine/lib/deprecated-1.9.php
new file mode 100644
index 000000000..31d03428f
--- /dev/null
+++ b/engine/lib/deprecated-1.9.php
@@ -0,0 +1,582 @@
+<?php
+/**
+ * Return a timestamp for the start of a given day (defaults today).
+ *
+ * @param int $day Day
+ * @param int $month Month
+ * @param int $year Year
+ *
+ * @return int
+ * @access private
+ * @deprecated 1.9
+ */
+function get_day_start($day = null, $month = null, $year = null) {
+ elgg_deprecated_notice('get_day_start() has been deprecated', 1.9);
+ return mktime(0, 0, 0, $month, $day, $year);
+}
+
+/**
+ * Return a timestamp for the end of a given day (defaults today).
+ *
+ * @param int $day Day
+ * @param int $month Month
+ * @param int $year Year
+ *
+ * @return int
+ * @access private
+ * @deprecated 1.9
+ */
+function get_day_end($day = null, $month = null, $year = null) {
+ elgg_deprecated_notice('get_day_end() has been deprecated', 1.9);
+ return mktime(23, 59, 59, $month, $day, $year);
+}
+
+/**
+ * Return the notable entities for a given time period.
+ *
+ * @param int $start_time The start time as a unix timestamp.
+ * @param int $end_time The end time as a unix timestamp.
+ * @param string $type The type of entity (eg "user", "object" etc)
+ * @param string $subtype The arbitrary subtype of the entity
+ * @param int $owner_guid The GUID of the owning user
+ * @param string $order_by The field to order by; by default, time_created desc
+ * @param int $limit The number of entities to return; 10 by default
+ * @param int $offset The indexing offset, 0 by default
+ * @param boolean $count Set to true to get a count instead of entities. Defaults to false.
+ * @param int $site_guid Site to get entities for. Default 0 = current site. -1 = any.
+ * @param mixed $container_guid Container or containers to get entities from (default: any).
+ *
+ * @return array|false
+ * @access private
+ * @deprecated 1.9
+ */
+function get_notable_entities($start_time, $end_time, $type = "", $subtype = "", $owner_guid = 0,
+$order_by = "asc", $limit = 10, $offset = 0, $count = false, $site_guid = 0,
+$container_guid = null) {
+ elgg_deprecated_notice('get_notable_entities() has been deprecated', 1.9);
+ global $CONFIG;
+
+ if ($subtype === false || $subtype === null || $subtype === 0) {
+ return false;
+ }
+
+ $start_time = (int)$start_time;
+ $end_time = (int)$end_time;
+ $order_by = sanitise_string($order_by);
+ $limit = (int)$limit;
+ $offset = (int)$offset;
+ $site_guid = (int) $site_guid;
+ if ($site_guid == 0) {
+ $site_guid = $CONFIG->site_guid;
+ }
+
+ $where = array();
+
+ if (is_array($type)) {
+ $tempwhere = "";
+ if (sizeof($type)) {
+ foreach ($type as $typekey => $subtypearray) {
+ foreach ($subtypearray as $subtypeval) {
+ $typekey = sanitise_string($typekey);
+ if (!empty($subtypeval)) {
+ $subtypeval = (int) get_subtype_id($typekey, $subtypeval);
+ } else {
+ $subtypeval = 0;
+ }
+ if (!empty($tempwhere)) {
+ $tempwhere .= " or ";
+ }
+ $tempwhere .= "(e.type = '{$typekey}' and e.subtype = {$subtypeval})";
+ }
+ }
+ }
+ if (!empty($tempwhere)) {
+ $where[] = "({$tempwhere})";
+ }
+ } else {
+ $type = sanitise_string($type);
+ $subtype = get_subtype_id($type, $subtype);
+
+ if ($type != "") {
+ $where[] = "e.type='$type'";
+ }
+
+ if ($subtype !== "") {
+ $where[] = "e.subtype=$subtype";
+ }
+ }
+
+ if ($owner_guid != "") {
+ if (!is_array($owner_guid)) {
+ $owner_array = array($owner_guid);
+ $owner_guid = (int) $owner_guid;
+ $where[] = "e.owner_guid = '$owner_guid'";
+ } else if (sizeof($owner_guid) > 0) {
+ $owner_array = array_map('sanitise_int', $owner_guid);
+ // Cast every element to the owner_guid array to int
+ $owner_guid = implode(",", $owner_guid);
+ $where[] = "e.owner_guid in ({$owner_guid})";
+ }
+ if (is_null($container_guid)) {
+ $container_guid = $owner_array;
+ }
+ }
+
+ if ($site_guid > 0) {
+ $where[] = "e.site_guid = {$site_guid}";
+ }
+
+ if (!is_null($container_guid)) {
+ if (is_array($container_guid)) {
+ foreach ($container_guid as $key => $val) {
+ $container_guid[$key] = (int) $val;
+ }
+ $where[] = "e.container_guid in (" . implode(",", $container_guid) . ")";
+ } else {
+ $container_guid = (int) $container_guid;
+ $where[] = "e.container_guid = {$container_guid}";
+ }
+ }
+
+ // Add the calendar stuff
+ $cal_join = "
+ JOIN {$CONFIG->dbprefix}metadata cal_start on e.guid=cal_start.entity_guid
+ JOIN {$CONFIG->dbprefix}metastrings cal_start_name on cal_start.name_id=cal_start_name.id
+ JOIN {$CONFIG->dbprefix}metastrings cal_start_value on cal_start.value_id=cal_start_value.id
+
+ JOIN {$CONFIG->dbprefix}metadata cal_end on e.guid=cal_end.entity_guid
+ JOIN {$CONFIG->dbprefix}metastrings cal_end_name on cal_end.name_id=cal_end_name.id
+ JOIN {$CONFIG->dbprefix}metastrings cal_end_value on cal_end.value_id=cal_end_value.id
+ ";
+ $where[] = "cal_start_name.string='calendar_start'";
+ $where[] = "cal_start_value.string>=$start_time";
+ $where[] = "cal_end_name.string='calendar_end'";
+ $where[] = "cal_end_value.string <= $end_time";
+
+
+ if (!$count) {
+ $query = "SELECT e.* from {$CONFIG->dbprefix}entities e $cal_join where ";
+ } else {
+ $query = "SELECT count(e.guid) as total from {$CONFIG->dbprefix}entities e $cal_join where ";
+ }
+ foreach ($where as $w) {
+ $query .= " $w and ";
+ }
+
+ $query .= get_access_sql_suffix('e'); // Add access controls
+
+ if (!$count) {
+ $query .= " order by n.calendar_start $order_by";
+ // Add order and limit
+ if ($limit) {
+ $query .= " limit $offset, $limit";
+ }
+ $dt = get_data($query, "entity_row_to_elggstar");
+
+ return $dt;
+ } else {
+ $total = get_data_row($query);
+ return $total->total;
+ }
+}
+
+/**
+ * Return the notable entities for a given time period based on an item of metadata.
+ *
+ * @param int $start_time The start time as a unix timestamp.
+ * @param int $end_time The end time as a unix timestamp.
+ * @param mixed $meta_name Metadata name
+ * @param mixed $meta_value Metadata value
+ * @param string $entity_type The type of entity to look for, eg 'site' or 'object'
+ * @param string $entity_subtype The subtype of the entity.
+ * @param int $owner_guid Owner GUID
+ * @param int $limit Limit
+ * @param int $offset Offset
+ * @param string $order_by Optional ordering.
+ * @param int $site_guid Site to get entities for. Default 0 = current site. -1 = any.
+ * @param bool $count If true, returns count instead of entities. (Default: false)
+ *
+ * @return int|array A list of entities, or a count if $count is set to true
+ * @access private
+ * @deprecated 1.9
+ */
+function get_notable_entities_from_metadata($start_time, $end_time, $meta_name, $meta_value = "",
+$entity_type = "", $entity_subtype = "", $owner_guid = 0, $limit = 10, $offset = 0, $order_by = "",
+$site_guid = 0, $count = false) {
+ elgg_deprecated_notice('get_notable_entities_from_metadata() has been deprecated', 1.9);
+
+ global $CONFIG;
+
+ $meta_n = get_metastring_id($meta_name);
+ $meta_v = get_metastring_id($meta_value);
+
+ $start_time = (int)$start_time;
+ $end_time = (int)$end_time;
+ $entity_type = sanitise_string($entity_type);
+ $entity_subtype = get_subtype_id($entity_type, $entity_subtype);
+ $limit = (int)$limit;
+ $offset = (int)$offset;
+ if ($order_by == "") {
+ $order_by = "e.time_created desc";
+ }
+ $order_by = sanitise_string($order_by);
+ $site_guid = (int) $site_guid;
+ if ((is_array($owner_guid) && (count($owner_guid)))) {
+ foreach ($owner_guid as $key => $guid) {
+ $owner_guid[$key] = (int) $guid;
+ }
+ } else {
+ $owner_guid = (int) $owner_guid;
+ }
+
+ if ($site_guid == 0) {
+ $site_guid = $CONFIG->site_guid;
+ }
+
+ //$access = get_access_list();
+
+ $where = array();
+
+ if ($entity_type != "") {
+ $where[] = "e.type='$entity_type'";
+ }
+
+ if ($entity_subtype) {
+ $where[] = "e.subtype=$entity_subtype";
+ }
+
+ if ($meta_name != "") {
+ $where[] = "m.name_id='$meta_n'";
+ }
+
+ if ($meta_value != "") {
+ $where[] = "m.value_id='$meta_v'";
+ }
+
+ if ($site_guid > 0) {
+ $where[] = "e.site_guid = {$site_guid}";
+ }
+
+ if (is_array($owner_guid)) {
+ $where[] = "e.container_guid in (" . implode(",", $owner_guid) . ")";
+ } else if ($owner_guid > 0) {
+ $where[] = "e.container_guid = {$owner_guid}";
+ }
+
+ // Add the calendar stuff
+ $cal_join = "
+ JOIN {$CONFIG->dbprefix}metadata cal_start on e.guid=cal_start.entity_guid
+ JOIN {$CONFIG->dbprefix}metastrings cal_start_name on cal_start.name_id=cal_start_name.id
+ JOIN {$CONFIG->dbprefix}metastrings cal_start_value on cal_start.value_id=cal_start_value.id
+
+ JOIN {$CONFIG->dbprefix}metadata cal_end on e.guid=cal_end.entity_guid
+ JOIN {$CONFIG->dbprefix}metastrings cal_end_name on cal_end.name_id=cal_end_name.id
+ JOIN {$CONFIG->dbprefix}metastrings cal_end_value on cal_end.value_id=cal_end_value.id
+ ";
+
+ $where[] = "cal_start_name.string='calendar_start'";
+ $where[] = "cal_start_value.string>=$start_time";
+ $where[] = "cal_end_name.string='calendar_end'";
+ $where[] = "cal_end_value.string <= $end_time";
+
+ if (!$count) {
+ $query = "SELECT distinct e.* ";
+ } else {
+ $query = "SELECT count(distinct e.guid) as total ";
+ }
+
+ $query .= "from {$CONFIG->dbprefix}entities e"
+ . " JOIN {$CONFIG->dbprefix}metadata m on e.guid = m.entity_guid $cal_join where";
+
+ foreach ($where as $w) {
+ $query .= " $w and ";
+ }
+
+ // Add access controls
+ $query .= get_access_sql_suffix("e");
+ $query .= ' and ' . get_access_sql_suffix("m");
+
+ if (!$count) {
+ // Add order and limit
+ $query .= " order by $order_by limit $offset, $limit";
+ return get_data($query, "entity_row_to_elggstar");
+ } else {
+ if ($row = get_data_row($query)) {
+ return $row->total;
+ }
+ }
+
+ return false;
+}
+
+/**
+ * Return the notable entities for a given time period based on their relationship.
+ *
+ * @param int $start_time The start time as a unix timestamp.
+ * @param int $end_time The end time as a unix timestamp.
+ * @param string $relationship The relationship eg "friends_of"
+ * @param int $relationship_guid The guid of the entity to use query
+ * @param bool $inverse_relationship Reverse the normal function of the query to say
+ * "give me all entities for whom $relationship_guid is a
+ * $relationship of"
+ * @param string $type Entity type
+ * @param string $subtype Entity subtype
+ * @param int $owner_guid Owner GUID
+ * @param string $order_by Optional Order by
+ * @param int $limit Limit
+ * @param int $offset Offset
+ * @param boolean $count If true returns a count of entities (default false)
+ * @param int $site_guid Site to get entities for. Default 0 = current site. -1 = any
+ *
+ * @return array|int|false An array of entities, or the number of entities, or false on failure
+ * @access private
+ * @deprecated 1.9
+ */
+function get_noteable_entities_from_relationship($start_time, $end_time, $relationship,
+$relationship_guid, $inverse_relationship = false, $type = "", $subtype = "", $owner_guid = 0,
+$order_by = "", $limit = 10, $offset = 0, $count = false, $site_guid = 0) {
+ elgg_deprecated_notice('get_noteable_entities_from_relationship() has been deprecated', 1.9);
+
+ global $CONFIG;
+
+ $start_time = (int)$start_time;
+ $end_time = (int)$end_time;
+ $relationship = sanitise_string($relationship);
+ $relationship_guid = (int)$relationship_guid;
+ $inverse_relationship = (bool)$inverse_relationship;
+ $type = sanitise_string($type);
+ $subtype = get_subtype_id($type, $subtype);
+ $owner_guid = (int)$owner_guid;
+ if ($order_by == "") {
+ $order_by = "time_created desc";
+ }
+ $order_by = sanitise_string($order_by);
+ $limit = (int)$limit;
+ $offset = (int)$offset;
+ $site_guid = (int) $site_guid;
+ if ($site_guid == 0) {
+ $site_guid = $CONFIG->site_guid;
+ }
+
+ //$access = get_access_list();
+
+ $where = array();
+
+ if ($relationship != "") {
+ $where[] = "r.relationship='$relationship'";
+ }
+ if ($relationship_guid) {
+ $where[] = $inverse_relationship ?
+ "r.guid_two='$relationship_guid'" : "r.guid_one='$relationship_guid'";
+ }
+ if ($type != "") {
+ $where[] = "e.type='$type'";
+ }
+ if ($subtype) {
+ $where[] = "e.subtype=$subtype";
+ }
+ if ($owner_guid != "") {
+ $where[] = "e.container_guid='$owner_guid'";
+ }
+ if ($site_guid > 0) {
+ $where[] = "e.site_guid = {$site_guid}";
+ }
+
+ // Add the calendar stuff
+ $cal_join = "
+ JOIN {$CONFIG->dbprefix}metadata cal_start on e.guid=cal_start.entity_guid
+ JOIN {$CONFIG->dbprefix}metastrings cal_start_name on cal_start.name_id=cal_start_name.id
+ JOIN {$CONFIG->dbprefix}metastrings cal_start_value on cal_start.value_id=cal_start_value.id
+
+ JOIN {$CONFIG->dbprefix}metadata cal_end on e.guid=cal_end.entity_guid
+ JOIN {$CONFIG->dbprefix}metastrings cal_end_name on cal_end.name_id=cal_end_name.id
+ JOIN {$CONFIG->dbprefix}metastrings cal_end_value on cal_end.value_id=cal_end_value.id
+ ";
+ $where[] = "cal_start_name.string='calendar_start'";
+ $where[] = "cal_start_value.string>=$start_time";
+ $where[] = "cal_end_name.string='calendar_end'";
+ $where[] = "cal_end_value.string <= $end_time";
+
+ // Select what we're joining based on the options
+ $joinon = "e.guid = r.guid_one";
+ if (!$inverse_relationship) {
+ $joinon = "e.guid = r.guid_two";
+ }
+
+ if ($count) {
+ $query = "SELECT count(distinct e.guid) as total ";
+ } else {
+ $query = "SELECT distinct e.* ";
+ }
+ $query .= " from {$CONFIG->dbprefix}entity_relationships r"
+ . " JOIN {$CONFIG->dbprefix}entities e on $joinon $cal_join where ";
+
+ foreach ($where as $w) {
+ $query .= " $w and ";
+ }
+ // Add access controls
+ $query .= get_access_sql_suffix("e");
+ if (!$count) {
+ $query .= " order by $order_by limit $offset, $limit"; // Add order and limit
+ return get_data($query, "entity_row_to_elggstar");
+ } else {
+ if ($count = get_data_row($query)) {
+ return $count->total;
+ }
+ }
+ return false;
+}
+
+/**
+ * Get all entities for today.
+ *
+ * @param string $type The type of entity (eg "user", "object" etc)
+ * @param string $subtype The arbitrary subtype of the entity
+ * @param int $owner_guid The GUID of the owning user
+ * @param string $order_by The field to order by; by default, time_created desc
+ * @param int $limit The number of entities to return; 10 by default
+ * @param int $offset The indexing offset, 0 by default
+ * @param boolean $count If true returns a count of entities (default false)
+ * @param int $site_guid Site to get entities for. Default 0 = current site. -1 = any
+ * @param mixed $container_guid Container(s) to get entities from (default: any).
+ *
+ * @return array|false
+ * @access private
+ * @deprecated 1.9
+ */
+function get_todays_entities($type = "", $subtype = "", $owner_guid = 0, $order_by = "",
+$limit = 10, $offset = 0, $count = false, $site_guid = 0, $container_guid = null) {
+ elgg_deprecated_notice('get_todays_entities() has been deprecated', 1.9);
+
+ $day_start = get_day_start();
+ $day_end = get_day_end();
+
+ return get_notable_entities($day_start, $day_end, $type, $subtype, $owner_guid, $order_by,
+ $limit, $offset, $count, $site_guid, $container_guid);
+}
+
+/**
+ * Get entities for today from metadata.
+ *
+ * @param mixed $meta_name Metadata name
+ * @param mixed $meta_value Metadata value
+ * @param string $entity_type The type of entity to look for, eg 'site' or 'object'
+ * @param string $entity_subtype The subtype of the entity.
+ * @param int $owner_guid Owner GUID
+ * @param int $limit Limit
+ * @param int $offset Offset
+ * @param string $order_by Optional ordering.
+ * @param int $site_guid Site to get entities for. Default 0 = current site. -1 = any.
+ * @param bool $count If true, returns count instead of entities. (Default: false)
+ *
+ * @return int|array A list of entities, or a count if $count is set to true
+ * @access private
+ * @deprecated 1.9
+ */
+function get_todays_entities_from_metadata($meta_name, $meta_value = "", $entity_type = "",
+$entity_subtype = "", $owner_guid = 0, $limit = 10, $offset = 0, $order_by = "", $site_guid = 0,
+$count = false) {
+ elgg_deprecated_notice('get_todays_entities_from_metadata() has been deprecated', 1.9);
+
+ $day_start = get_day_start();
+ $day_end = get_day_end();
+
+ return get_notable_entities_from_metadata($day_start, $day_end, $meta_name, $meta_value,
+ $entity_type, $entity_subtype, $owner_guid, $limit, $offset, $order_by, $site_guid, $count);
+}
+
+/**
+ * Get entities for today from a relationship
+ *
+ * @param string $relationship The relationship eg "friends_of"
+ * @param int $relationship_guid The guid of the entity to use query
+ * @param bool $inverse_relationship Reverse the normal function of the query to say
+ * "give me all entities for whom $relationship_guid is a
+ * $relationship of"
+ * @param string $type Entity type
+ * @param string $subtype Entity subtype
+ * @param int $owner_guid Owner GUID
+ * @param string $order_by Optional Order by
+ * @param int $limit Limit
+ * @param int $offset Offset
+ * @param boolean $count If true returns a count of entities (default false)
+ * @param int $site_guid Site to get entities for. Default 0 = current site. -1 = any
+ *
+ * @return array|int|false An array of entities, or the number of entities, or false on failure
+ * @access private
+ * @deprecated 1.9
+ */
+function get_todays_entities_from_relationship($relationship, $relationship_guid,
+$inverse_relationship = false, $type = "", $subtype = "", $owner_guid = 0,
+$order_by = "", $limit = 10, $offset = 0, $count = false, $site_guid = 0) {
+ elgg_deprecated_notice('get_todays_entities_from_relationship() has been deprecated', 1.9);
+
+ $day_start = get_day_start();
+ $day_end = get_day_end();
+
+ return get_notable_entities_from_relationship($day_start, $day_end, $relationship,
+ $relationship_guid, $inverse_relationship, $type, $subtype, $owner_guid, $order_by,
+ $limit, $offset, $count, $site_guid);
+}
+
+/**
+ * Returns a viewable list of entities for a given time period.
+ *
+ * @see elgg_view_entity_list
+ *
+ * @param int $start_time The start time as a unix timestamp.
+ * @param int $end_time The end time as a unix timestamp.
+ * @param string $type The type of entity (eg "user", "object" etc)
+ * @param string $subtype The arbitrary subtype of the entity
+ * @param int $owner_guid The GUID of the owning user
+ * @param int $limit The number of entities to return; 10 by default
+ * @param boolean $fullview Whether or not to display the full view (default: true)
+ * @param boolean $listtypetoggle Whether or not to allow gallery view
+ * @param boolean $navigation Display pagination? Default: true
+ *
+ * @return string A viewable list of entities
+ * @access private
+ * @deprecated 1.9
+ */
+function list_notable_entities($start_time, $end_time, $type= "", $subtype = "", $owner_guid = 0,
+$limit = 10, $fullview = true, $listtypetoggle = false, $navigation = true) {
+ elgg_deprecated_notice('list_notable_entities() has been deprecated', 1.9);
+
+ $offset = (int) get_input('offset');
+ $count = get_notable_entities($start_time, $end_time, $type, $subtype,
+ $owner_guid, "", $limit, $offset, true);
+
+ $entities = get_notable_entities($start_time, $end_time, $type, $subtype,
+ $owner_guid, "", $limit, $offset);
+
+ return elgg_view_entity_list($entities, $count, $offset, $limit,
+ $fullview, $listtypetoggle, $navigation);
+}
+
+/**
+ * Return a list of today's entities.
+ *
+ * @see list_notable_entities
+ *
+ * @param string $type The type of entity (eg "user", "object" etc)
+ * @param string $subtype The arbitrary subtype of the entity
+ * @param int $owner_guid The GUID of the owning user
+ * @param int $limit The number of entities to return; 10 by default
+ * @param boolean $fullview Whether or not to display the full view (default: true)
+ * @param boolean $listtypetoggle Whether or not to allow gallery view
+ * @param boolean $navigation Display pagination? Default: true
+ *
+ * @return string A viewable list of entities
+ * @access private
+ * @deprecated 1.9
+ */
+function list_todays_entities($type= "", $subtype = "", $owner_guid = 0, $limit = 10,
+$fullview = true, $listtypetoggle = false, $navigation = true) {
+ elgg_deprecated_notice('list_todays_entities() has been deprecated', 1.9);
+
+ $day_start = get_day_start();
+ $day_end = get_day_end();
+
+ return list_notable_entities($day_start, $day_end, $type, $subtype, $owner_guid, $limit,
+ $fullview, $listtypetoggle, $navigation);
+}
diff --git a/engine/lib/elgglib.php b/engine/lib/elgglib.php
index fb652a141..34111c69d 100644
--- a/engine/lib/elgglib.php
+++ b/engine/lib/elgglib.php
@@ -746,7 +746,7 @@ function elgg_unregister_event_handler($event, $object_type, $callback) {
* @tip When referring to events, the preferred syntax is "event, type".
*
* @internal Only rarely should events be changed, added, or removed in core.
- * When making changes to events, be sure to first create a ticket in trac.
+ * When making changes to events, be sure to first create a ticket on Github.
*
* @internal @tip Think of $object_type as the primary namespace element, and
* $event as the secondary namespace.
@@ -1350,7 +1350,7 @@ function full_url() {
"" : (":" . $_SERVER["SERVER_PORT"]);
// This is here to prevent XSS in poorly written browsers used by 80% of the population.
- // {@trac [5813]}
+ // https://github.com/Elgg/Elgg/commit/0c947e80f512cb0a482b1864fd0a6965c8a0cd4a
$quotes = array('\'', '"');
$encoded = array('%27', '%22');
@@ -2247,6 +2247,9 @@ function elgg_api_test($hook, $type, $value, $params) {
/**#@+
* Controls access levels on ElggEntity entities, metadata, and annotations.
*
+ * @warning ACCESS_DEFAULT is a place holder for the input/access view. Do not
+ * use it when saving an entity.
+ *
* @var int
*/
define('ACCESS_DEFAULT', -1);
diff --git a/engine/lib/entities.php b/engine/lib/entities.php
index cb972b282..4fcf1c657 100644
--- a/engine/lib/entities.php
+++ b/engine/lib/entities.php
@@ -17,6 +17,15 @@ global $ENTITY_CACHE;
$ENTITY_CACHE = array();
/**
+ * GUIDs of entities banned from the entity cache (during this request)
+ *
+ * @global array $ENTITY_CACHE_DISABLED_GUIDS
+ * @access private
+ */
+global $ENTITY_CACHE_DISABLED_GUIDS;
+$ENTITY_CACHE_DISABLED_GUIDS = array();
+
+/**
* Cache subtypes and related class names.
*
* @global array|null $SUBTYPE_CACHE array once populated from DB, initially null
@@ -26,6 +35,34 @@ global $SUBTYPE_CACHE;
$SUBTYPE_CACHE = null;
/**
+ * Remove this entity from the entity cache and make sure it is not re-added
+ *
+ * @param int $guid The entity guid
+ *
+ * @access private
+ * @todo this is a workaround until #5604 can be implemented
+ */
+function _elgg_disable_caching_for_entity($guid) {
+ global $ENTITY_CACHE_DISABLED_GUIDS;
+
+ _elgg_invalidate_cache_for_entity($guid);
+ $ENTITY_CACHE_DISABLED_GUIDS[$guid] = true;
+}
+
+/**
+ * Allow this entity to be stored in the entity cache
+ *
+ * @param int $guid The entity guid
+ *
+ * @access private
+ */
+function _elgg_enable_caching_for_entity($guid) {
+ global $ENTITY_CACHE_DISABLED_GUIDS;
+
+ unset($ENTITY_CACHE_DISABLED_GUIDS[$guid]);
+}
+
+/**
* Invalidate this class's entry in the cache.
*
* @param int $guid The entity guid
@@ -57,7 +94,7 @@ function _elgg_invalidate_cache_for_entity($guid) {
* @todo Use an ElggCache object
*/
function _elgg_cache_entity(ElggEntity $entity) {
- global $ENTITY_CACHE;
+ global $ENTITY_CACHE, $ENTITY_CACHE_DISABLED_GUIDS;
// Don't cache non-plugin entities while access control is off, otherwise they could be
// exposed to users who shouldn't see them when control is re-enabled.
@@ -65,6 +102,11 @@ function _elgg_cache_entity(ElggEntity $entity) {
return;
}
+ $guid = $entity->getGUID();
+ if (isset($ENTITY_CACHE_DISABLED_GUIDS[$guid])) {
+ return;
+ }
+
// Don't store too many or we'll have memory problems
// @todo Pick a less arbitrary limit
if (count($ENTITY_CACHE) > 256) {
@@ -79,7 +121,7 @@ function _elgg_cache_entity(ElggEntity $entity) {
elgg_get_metadata_cache()->clear($random_guid);
}
- $ENTITY_CACHE[$entity->guid] = $entity;
+ $ENTITY_CACHE[$guid] = $entity;
}
/**
@@ -407,7 +449,7 @@ function update_subtype($type, $subtype, $class = '') {
* @param int $time_created The time creation timestamp
*
* @return bool
- * @link http://docs.elgg.org/DataModel/Entities
+ * @throws InvalidParameterException
* @access private
*/
function update_entity($guid, $owner_guid, $access_id, $container_guid = null, $time_created = null) {
@@ -430,6 +472,10 @@ function update_entity($guid, $owner_guid, $access_id, $container_guid = null, $
$time_created = (int) $time_created;
}
+ if ($access_id == ACCESS_DEFAULT) {
+ throw new InvalidParameterException('ACCESS_DEFAULT is not a valid access level. See its documentation in elgglib.h');
+ }
+
if ($entity && $entity->canEdit()) {
if (elgg_trigger_event('update', $entity->type, $entity)) {
$ret = update_data("UPDATE {$CONFIG->dbprefix}entities
@@ -556,7 +602,6 @@ $container_guid = 0) {
$type = sanitise_string($type);
$subtype_id = add_subtype($type, $subtype);
$owner_guid = (int)$owner_guid;
- $access_id = (int)$access_id;
$time = time();
if ($site_guid == 0) {
$site_guid = $CONFIG->site_guid;
@@ -565,6 +610,10 @@ $container_guid = 0) {
if ($container_guid == 0) {
$container_guid = $owner_guid;
}
+ $access_id = (int)$access_id;
+ if ($access_id == ACCESS_DEFAULT) {
+ throw new InvalidParameterException('ACCESS_DEFAULT is not a valid access level. See its documentation in elgglib.h');
+ }
$user_guid = elgg_get_logged_in_user_guid();
if (!can_write_to_container($user_guid, $owner_guid, $type, $subtype)) {
@@ -712,7 +761,7 @@ function get_entity($guid) {
// @todo We need a single Memcache instance with a shared pool of namespace wrappers. This function would pull an instance from the pool.
static $shared_cache;
- // We could also use: if (!(int) $guid) { return FALSE },
+ // We could also use: if (!(int) $guid) { return FALSE },
// but that evaluates to a false positive for $guid = TRUE.
// This is a bit slower, but more thorough.
if (!is_numeric($guid) || $guid === 0 || $guid === '0') {
@@ -742,7 +791,7 @@ function get_entity($guid) {
if ($shared_cache) {
$cached_entity = $shared_cache->load($guid);
- // @todo store ACLs in memcache http://trac.elgg.org/ticket/3018#comment:3
+ // @todo store ACLs in memcache https://github.com/elgg/elgg/issues/3018#issuecomment-13662617
if ($cached_entity) {
// @todo use ACL and cached entity access_id to determine if user can see it
return $cached_entity;
@@ -884,6 +933,8 @@ function elgg_get_entities(array $options = array()) {
'joins' => array(),
'callback' => 'entity_row_to_elggstar',
+
+ '__ElggBatch' => null,
);
$options = array_merge($defaults, $options);
@@ -1001,7 +1052,7 @@ function elgg_get_entities(array $options = array()) {
}
if ($options['callback'] === 'entity_row_to_elggstar') {
- $dt = _elgg_fetch_entities_from_sql($query);
+ $dt = _elgg_fetch_entities_from_sql($query, $options['__ElggBatch']);
} else {
$dt = get_data($query, $options['callback']);
}
@@ -1036,13 +1087,14 @@ function elgg_get_entities(array $options = array()) {
/**
* Return entities from an SQL query generated by elgg_get_entities.
*
- * @param string $sql
+ * @param string $sql
+ * @param ElggBatch $batch
* @return ElggEntity[]
*
* @access private
* @throws LogicException
*/
-function _elgg_fetch_entities_from_sql($sql) {
+function _elgg_fetch_entities_from_sql($sql, ElggBatch $batch = null) {
static $plugin_subtype;
if (null === $plugin_subtype) {
$plugin_subtype = get_subtype_id('object', 'plugin');
@@ -1119,6 +1171,11 @@ function _elgg_fetch_entities_from_sql($sql) {
} catch (IncompleteEntityException $e) {
// don't let incomplete entities throw fatal errors
unset($rows[$i]);
+
+ // report incompletes to the batch process that spawned this query
+ if ($batch) {
+ $batch->reportIncompleteEntity($row);
+ }
}
}
}
@@ -1416,8 +1473,10 @@ function elgg_list_entities(array $options = array(), $getter = 'elgg_get_entiti
global $autofeed;
$autofeed = true;
+ $offset_key = isset($options['offset_key']) ? $options['offset_key'] : 'offset';
+
$defaults = array(
- 'offset' => (int) max(get_input('offset', 0), 0),
+ 'offset' => (int) max(get_input($offset_key, 0), 0),
'limit' => (int) max(get_input('limit', 10), 0),
'full_view' => TRUE,
'list_type_toggle' => FALSE,
@@ -1619,8 +1678,8 @@ function disable_entity($guid, $reason = "", $recursive = true) {
/**
* Enable an entity.
*
- * @warning In order to enable an entity using ElggEntity::enable(),
- * you must first use {@link access_show_hidden_entities()}.
+ * @warning In order to enable an entity, you must first use
+ * {@link access_show_hidden_entities()}.
*
* @param int $guid GUID of entity to enable
* @param bool $recursive Recursively enable all entities disabled with the entity?
@@ -1748,6 +1807,10 @@ function delete_entity($guid, $recursive = true) {
elgg_set_ignore_access($ia);
}
+ $entity_disable_override = access_get_show_hidden_status();
+ access_show_hidden_entities(true);
+ $ia = elgg_set_ignore_access(true);
+
// Now delete the entity itself
$entity->deleteMetadata();
$entity->deleteOwnedMetadata();
@@ -1755,6 +1818,9 @@ function delete_entity($guid, $recursive = true) {
$entity->deleteOwnedAnnotations();
$entity->deleteRelationships();
+ access_show_hidden_entities($entity_disable_override);
+ elgg_set_ignore_access($ia);
+
elgg_delete_river(array('subject_guid' => $guid));
elgg_delete_river(array('object_guid' => $guid));
remove_all_private_settings($guid);
@@ -2062,7 +2128,7 @@ function can_edit_entity_metadata($entity_guid, $user_guid = 0, $metadata = null
$return = null;
- if ($metadata->owner_guid == 0) {
+ if ($metadata && ($metadata->owner_guid == 0)) {
$return = true;
}
if (is_null($return)) {
@@ -2463,11 +2529,18 @@ function update_entity_last_action($guid, $posted = NULL) {
function entities_gc() {
global $CONFIG;
- $tables = array ('sites_entity', 'objects_entity', 'groups_entity', 'users_entity');
+ $tables = array(
+ 'site' => 'sites_entity',
+ 'object' => 'objects_entity',
+ 'group' => 'groups_entity',
+ 'user' => 'users_entity'
+ );
- foreach ($tables as $table) {
- delete_data("DELETE from {$CONFIG->dbprefix}{$table}
- where guid NOT IN (SELECT guid from {$CONFIG->dbprefix}entities)");
+ foreach ($tables as $type => $table) {
+ delete_data("DELETE FROM {$CONFIG->dbprefix}{$table}
+ WHERE guid NOT IN (SELECT guid FROM {$CONFIG->dbprefix}entities)");
+ delete_data("DELETE FROM {$CONFIG->dbprefix}entities
+ WHERE type = '$type' AND guid NOT IN (SELECT guid FROM {$CONFIG->dbprefix}{$table})");
}
}
diff --git a/engine/lib/extender.php b/engine/lib/extender.php
index 8756e051b..8323bd3ce 100644
--- a/engine/lib/extender.php
+++ b/engine/lib/extender.php
@@ -126,14 +126,20 @@ function import_extender_plugin_hook($hook, $entity_type, $returnvalue, $params)
* @return bool
*/
function can_edit_extender($extender_id, $type, $user_guid = 0) {
- if (!elgg_is_logged_in()) {
- return false;
+ // @todo Since Elgg 1.0, Elgg has returned false from can_edit_extender()
+ // if no user was logged in. This breaks the access override. This is a
+ // temporary work around. This function needs to be rewritten in Elgg 1.9
+ if (!elgg_check_access_overrides($user_guid)) {
+ if (!elgg_is_logged_in()) {
+ return false;
+ }
}
$user_guid = (int)$user_guid;
- $user = get_entity($user_guid);
+ $user = get_user($user_guid);
if (!$user) {
$user = elgg_get_logged_in_user_entity();
+ $user_guid = elgg_get_logged_in_user_guid();
}
$functionname = "elgg_get_{$type}_from_id";
@@ -149,16 +155,16 @@ function can_edit_extender($extender_id, $type, $user_guid = 0) {
/* @var ElggExtender $extender */
// If the owner is the specified user, great! They can edit.
- if ($extender->getOwnerGUID() == $user->getGUID()) {
+ if ($extender->getOwnerGUID() == $user_guid) {
return true;
}
// If the user can edit the entity this is attached to, great! They can edit.
- if (can_edit_entity($extender->entity_guid, $user->getGUID())) {
+ if (can_edit_entity($extender->entity_guid, $user_guid)) {
return true;
}
- // Trigger plugin hooks
+ // Trigger plugin hook - note that $user may be null
$params = array('entity' => $extender->getEntity(), 'user' => $user);
return elgg_trigger_plugin_hook('permissions_check', $type, $params, false);
}
diff --git a/engine/lib/group.php b/engine/lib/group.php
index 359bc59c2..6ded8a825 100644
--- a/engine/lib/group.php
+++ b/engine/lib/group.php
@@ -240,6 +240,7 @@ function leave_group($group_guid, $user_guid) {
*/
function get_users_membership($user_guid) {
$options = array(
+ 'type' => 'group',
'relationship' => 'member',
'relationship_guid' => $user_guid,
'inverse_relationship' => false,
diff --git a/engine/lib/input.php b/engine/lib/input.php
index 2d9bae4dd..80b0b8766 100644
--- a/engine/lib/input.php
+++ b/engine/lib/input.php
@@ -60,8 +60,8 @@ function get_input($variable, $default = NULL, $filter_result = TRUE) {
*
* Note: this function does not handle nested arrays (ex: form input of param[m][n])
*
- * @param string $variable The name of the variable
- * @param string $value The value of the variable
+ * @param string $variable The name of the variable
+ * @param string|string[] $value The value of the variable
*
* @return void
*/
diff --git a/engine/lib/memcache.php b/engine/lib/memcache.php
index f79fba4a9..79b87e850 100644
--- a/engine/lib/memcache.php
+++ b/engine/lib/memcache.php
@@ -35,3 +35,23 @@ function is_memcache_available() {
return $memcache_available;
}
+
+/**
+ * Invalidate an entity in memcache
+ *
+ * @param int $entity_guid The GUID of the entity to invalidate
+ *
+ * @return void
+ * @access private
+ */
+function _elgg_invalidate_memcache_for_entity($entity_guid) {
+ static $newentity_cache;
+
+ if ((!$newentity_cache) && (is_memcache_available())) {
+ $newentity_cache = new ElggMemcache('new_entity_cache');
+ }
+
+ if ($newentity_cache) {
+ $newentity_cache->delete($entity_guid);
+ }
+} \ No newline at end of file
diff --git a/engine/lib/metadata.php b/engine/lib/metadata.php
index ad926a49a..fdb1b85f6 100644
--- a/engine/lib/metadata.php
+++ b/engine/lib/metadata.php
@@ -191,19 +191,19 @@ function update_metadata($id, $name, $value, $value_type, $owner_guid, $access_i
}
// Add the metastring
- $value = add_metastring($value);
- if (!$value) {
+ $value_id = add_metastring($value);
+ if (!$value_id) {
return false;
}
- $name = add_metastring($name);
- if (!$name) {
+ $name_id = add_metastring($name);
+ if (!$name_id) {
return false;
}
// If ok then add it
$query = "UPDATE {$CONFIG->dbprefix}metadata"
- . " set name_id='$name', value_id='$value', value_type='$value_type', access_id=$access_id,"
+ . " set name_id='$name_id', value_id='$value_id', value_type='$value_type', access_id=$access_id,"
. " owner_guid=$owner_guid where id=$id";
$result = update_data($query);
@@ -300,10 +300,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.
+ * @return bool|null true on success, false on failure, null if no metadata to delete.
* @since 1.8.0
*/
function elgg_delete_metadata(array $options) {
@@ -325,10 +323,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
+ * @return bool|null true on success, false on failure, null if no metadata disabled.
* @since 1.8.0
*/
function elgg_disable_metadata(array $options) {
@@ -337,9 +333,13 @@ function elgg_disable_metadata(array $options) {
}
elgg_get_metadata_cache()->invalidateByOptions('disable', $options);
+
+ // if we can see hidden (disabled) we need to use the offset
+ // otherwise we risk an infinite loop if there are more than 50
+ $inc_offset = access_get_show_hidden_status();
$options['metastring_type'] = 'metadata';
- return elgg_batch_metastring_based_objects($options, 'elgg_batch_disable_callback', false);
+ return elgg_batch_metastring_based_objects($options, 'elgg_batch_disable_callback', $inc_offset);
}
/**
@@ -347,10 +347,11 @@ 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.
+ * @warning In order to enable metadata, you must first use
+ * {@link access_show_hidden_entities()}.
*
* @param array $options An options array. {@See elgg_get_metadata()}
- * @return mixed
+ * @return bool|null true on success, false on failure, null if no metadata enabled.
* @since 1.8.0
*/
function elgg_enable_metadata(array $options) {
@@ -405,9 +406,11 @@ function elgg_enable_metadata(array $options) {
* 'operand' => '=',
* 'case_sensitive' => TRUE
* )
- * Currently if multiple values are sent via
+ * Currently if multiple values are sent via
* an array (value => array('value1', 'value2')
* the pair's operand will be forced to "IN".
+ * If passing "IN" as the operand and a string as the value,
+ * the value must be a properly quoted and escaped string.
*
* metadata_name_value_pairs_operator => NULL|STR The operator to use for combining
* (name = value) OPERATOR (name = value); default AND
diff --git a/engine/lib/metastrings.php b/engine/lib/metastrings.php
index f49b4a163..57d876c06 100644
--- a/engine/lib/metastrings.php
+++ b/engine/lib/metastrings.php
@@ -421,9 +421,11 @@ function elgg_get_metastring_based_objects($options) {
if ($metastring_clauses) {
$wheres = array_merge($wheres, $metastring_clauses['wheres']);
$joins = array_merge($joins, $metastring_clauses['joins']);
+ } else {
+ $wheres[] = get_access_sql_suffix('n_table');
}
- if ($options['metastring_calculation'] === ELGG_ENTITIES_NO_VALUE) {
+ if ($options['metastring_calculation'] === ELGG_ENTITIES_NO_VALUE && !$options['count']) {
$selects = array_unique($selects);
// evalutate selects
$select_str = '';
@@ -434,6 +436,9 @@ function elgg_get_metastring_based_objects($options) {
}
$query = "SELECT DISTINCT n_table.*{$select_str} FROM {$db_prefix}$type n_table";
+ } elseif ($options['count']) {
+ // count is over the entities
+ $query = "SELECT count(DISTINCT e.guid) as calculation FROM {$db_prefix}$type n_table";
} else {
$query = "SELECT {$options['metastring_calculation']}(v.string) as calculation FROM {$db_prefix}$type n_table";
}
@@ -462,7 +467,7 @@ function elgg_get_metastring_based_objects($options) {
$defaults['order_by']);
}
- if ($options['metastring_calculation'] === ELGG_ENTITIES_NO_VALUE) {
+ if ($options['metastring_calculation'] === ELGG_ENTITIES_NO_VALUE && !$options['count']) {
if (isset($options['group_by'])) {
$options['group_by'] = sanitise_string($options['group_by']);
$query .= " GROUP BY {$options['group_by']}";
@@ -510,7 +515,7 @@ function elgg_get_metastring_sql($table, $names = null, $values = null,
&& !$ids
&& (!$pairs && $pairs !== 0)) {
- return '';
+ return array();
}
$db_prefix = elgg_get_config('dbprefix');
@@ -520,8 +525,6 @@ function elgg_get_metastring_sql($table, $names = null, $values = null,
// only supported on values.
$binary = ($case_sensitive) ? ' BINARY ' : '';
- $access = get_access_sql_suffix($table);
-
$return = array (
'joins' => array (),
'wheres' => array()
@@ -586,13 +589,15 @@ function elgg_get_metastring_sql($table, $names = null, $values = null,
}
if ($names_where && $values_where) {
- $wheres[] = "($names_where AND $values_where AND $access)";
+ $wheres[] = "($names_where AND $values_where)";
} elseif ($names_where) {
- $wheres[] = "($names_where AND $access)";
+ $wheres[] = $names_where;
} elseif ($values_where) {
- $wheres[] = "($values_where AND $access)";
+ $wheres[] = $values_where;
}
+ $wheres[] = get_access_sql_suffix($table);
+
if ($where = implode(' AND ', $wheres)) {
$return['wheres'][] = "($where)";
}
diff --git a/engine/lib/navigation.php b/engine/lib/navigation.php
index 118a7214c..ab9cc05e8 100644
--- a/engine/lib/navigation.php
+++ b/engine/lib/navigation.php
@@ -218,7 +218,7 @@ function elgg_push_breadcrumb($title, $link = NULL) {
}
// avoid key collisions.
- $CONFIG->breadcrumbs[] = array('title' => $title, 'link' => $link);
+ $CONFIG->breadcrumbs[] = array('title' => elgg_get_excerpt($title, 100), 'link' => $link);
}
/**
@@ -323,7 +323,8 @@ function elgg_site_menu_setup($hook, $type, $return, $params) {
}
if (!$selected) {
- // nothing selected, match name to context
+ // nothing selected, match name to context or match url
+ $current_url = current_page_url();
foreach ($return as $section_name => $section) {
foreach ($section as $key => $item) {
// only highlight internal links
@@ -332,6 +333,10 @@ function elgg_site_menu_setup($hook, $type, $return, $params) {
$return[$section_name][$key]->setSelected(true);
break 2;
}
+ if ($item->getHref() == $current_url) {
+ $return[$section_name][$key]->setSelected(true);
+ break 2;
+ }
}
}
}
diff --git a/engine/lib/notification.php b/engine/lib/notification.php
index b6399b3c6..be0c359d4 100644
--- a/engine/lib/notification.php
+++ b/engine/lib/notification.php
@@ -110,12 +110,15 @@ function notify_user($to, $from, $subject, $message, array $params = NULL, $meth
// Are we overriding delivery?
$methods = $methods_override;
if (!$methods) {
- $tmp = (array)get_user_notification_settings($guid);
+ $tmp = get_user_notification_settings($guid);
$methods = array();
- foreach ($tmp as $k => $v) {
- // Add method if method is turned on for user!
- if ($v) {
- $methods[] = $k;
+ // $tmp may be false. don't cast
+ if (is_object($tmp)) {
+ foreach ($tmp as $k => $v) {
+ // Add method if method is turned on for user!
+ if ($v) {
+ $methods[] = $k;
+ }
}
}
}
@@ -165,7 +168,7 @@ function notify_user($to, $from, $subject, $message, array $params = NULL, $meth
*
* @param int $user_guid The user id
*
- * @return stdClass
+ * @return stdClass|false
*/
function get_user_notification_settings($user_guid = 0) {
$user_guid = (int)$user_guid;
diff --git a/engine/lib/output.php b/engine/lib/output.php
index 6905b9b71..de4f911fb 100644
--- a/engine/lib/output.php
+++ b/engine/lib/output.php
@@ -27,16 +27,16 @@ function parse_urls($text) {
// By default htmlawed rewrites tags to this format.
// if PHP supported conditional negative lookbehinds we could use this:
// $r = preg_replace_callback('/(?<!=)(?<![ ])?(?<!["\'])((ht|f)tps?:\/\/[^\s\r\n\t<>"\'\!\(\),]+)/i',
- $r = preg_replace_callback('/(?<!=)(?<!["\'])((ht|f)tps?:\/\/[^\s\r\n\t<>"\'\(\)]+)/i',
+ $r = preg_replace_callback('/(?<![=\/"\'])((ht|f)tps?:\/\/[^\s\r\n\t<>"\']+)/i',
create_function(
'$matches',
'
$url = $matches[1];
- $punc = \'\';
+ $punc = "";
$last = substr($url, -1, 1);
- if (in_array($last, array(".", "!", ","))) {
+ if (in_array($last, array(".", "!", ",", "(", ")"))) {
$punc = $last;
- $url = rtrim($url, ".!,");
+ $url = rtrim($url, ".!,()");
}
$urltext = str_replace("/", "/<wbr />", $url);
return "<a href=\"$url\" rel=\"nofollow\">$urltext</a>$punc";
@@ -421,6 +421,25 @@ function _elgg_html_decode($string) {
}
/**
+ * Prepares query string for output to prevent CSRF attacks.
+ *
+ * @param string $string
+ * @return string
+ *
+ * @access private
+ */
+function _elgg_get_display_query($string) {
+ //encode <,>,&, quotes and characters above 127
+ if (function_exists('mb_convert_encoding')) {
+ $display_query = mb_convert_encoding($string, 'HTML-ENTITIES', 'UTF-8');
+ } else {
+ // if no mbstring extension, we just strip characters
+ $display_query = preg_replace("/[^\x01-\x7F]/", "", $string);
+ }
+ return htmlspecialchars($display_query, ENT_QUOTES, 'UTF-8', false);
+}
+
+/**
* Unit tests for Output
*
* @param string $hook unit_test
diff --git a/engine/lib/plugins.php b/engine/lib/plugins.php
index 74bce45fd..d5d3db466 100644
--- a/engine/lib/plugins.php
+++ b/engine/lib/plugins.php
@@ -1105,6 +1105,49 @@ function plugins_test($hook, $type, $value, $params) {
}
/**
+ * Checks on deactivate plugin event if disabling it won't create unmet dependencies and blocks disable in such case.
+ *
+ * @param string $event deactivate
+ * @param string $type plugin
+ * @param array $params Parameters array containing entry with ELggPlugin instance under 'plugin_entity' key
+ * @return bool false to block plugin deactivation action
+ *
+ * @access private
+ */
+function _plugins_deactivate_dependency_check($event, $type, $params) {
+ $plugin_id = $params['plugin_entity']->getManifest()->getPluginID();
+ $plugin_name = $params['plugin_entity']->getManifest()->getName();
+
+ $active_plugins = elgg_get_plugins();
+
+ $dependents = array();
+ foreach ($active_plugins as $plugin) {
+ $manifest = $plugin->getManifest();
+ $requires = $manifest->getRequires();
+
+ foreach ($requires as $required) {
+ if ($required['type'] == 'plugin' && $required['name'] == $plugin_id) {
+ // there are active dependents
+ $dependents[$manifest->getPluginID()] = $plugin;
+ }
+ }
+ }
+
+ if ($dependents) {
+ $list = '<ul>';
+ // construct error message and prevent disabling
+ foreach ($dependents as $dependent) {
+ $list .= '<li>' . $dependent->getManifest()->getName() . '</li>';
+ }
+ $list .= '</ul>';
+
+ register_error(elgg_echo('ElggPlugin:Dependencies:ActiveDependent', array($plugin_name, $list)));
+
+ return false;
+ }
+}
+
+/**
* Initialize the plugin system
* Listens to system init and registers actions
*
@@ -1115,6 +1158,10 @@ function plugin_init() {
run_function_once("plugin_run_once");
elgg_register_plugin_hook_handler('unit_test', 'system', 'plugins_test');
+
+ // note - plugins are booted by the time this handler is registered
+ // deactivation due to error may have already occurred
+ elgg_register_event_handler('deactivate', 'plugin', '_plugins_deactivate_dependency_check');
elgg_register_action("plugins/settings/save", '', 'admin');
elgg_register_action("plugins/usersettings/save");
diff --git a/engine/lib/river.php b/engine/lib/river.php
index 4926a85c4..e92040eb7 100644
--- a/engine/lib/river.php
+++ b/engine/lib/river.php
@@ -120,7 +120,7 @@ $posted = 0, $annotation_id = 0) {
* subtypes => STR|ARR Entity subtype string(s)
* type_subtype_pairs => ARR Array of type => subtype pairs where subtype
* can be an array of subtype strings
- *
+ *
* posted_time_lower => INT The lower bound on the time posted
* posted_time_upper => INT The upper bound on the time posted
*
@@ -434,8 +434,13 @@ function elgg_list_river(array $options = array()) {
'pagination' => TRUE,
'list_class' => 'elgg-list-river elgg-river', // @todo remove elgg-river in Elgg 1.9
);
-
+
$options = array_merge($defaults, $options);
+
+ if (!$options["limit"] && !$options["offset"]) {
+ // no need for pagination if listing is unlimited
+ $options["pagination"] = false;
+ }
$options['count'] = TRUE;
$count = elgg_get_river($options);
@@ -445,6 +450,7 @@ function elgg_list_river(array $options = array()) {
$options['count'] = $count;
$options['items'] = $items;
+
return elgg_view('page/components/list', $options);
}
diff --git a/engine/lib/sessions.php b/engine/lib/sessions.php
index a34c2045b..e3d5ce9cd 100644
--- a/engine/lib/sessions.php
+++ b/engine/lib/sessions.php
@@ -87,6 +87,9 @@ function elgg_is_admin_logged_in() {
*/
function elgg_is_admin_user($user_guid) {
global $CONFIG;
+
+ $user_guid = (int)$user_guid;
+
// cannot use magic metadata here because of recursion
// must support the old way of getting admin from metadata
@@ -323,6 +326,12 @@ function login(ElggUser $user, $persistent = false) {
set_last_login($_SESSION['guid']);
reset_login_failure_count($user->guid); // Reset any previous failed login attempts
+ // if memcache is enabled, invalidate the user in memcache @see https://github.com/Elgg/Elgg/issues/3143
+ if (is_memcache_available()) {
+ // this needs to happen with a shutdown function because of the timing with set_last_login()
+ register_shutdown_function("_elgg_invalidate_memcache_for_entity", $_SESSION['guid']);
+ }
+
return true;
}
diff --git a/engine/lib/statistics.php b/engine/lib/statistics.php
index 0c9a3c945..4cb0bb0b8 100644
--- a/engine/lib/statistics.php
+++ b/engine/lib/statistics.php
@@ -95,13 +95,17 @@ function get_number_users($show_deactivated = false) {
* @return string
*/
function get_online_users() {
- $count = find_active_users(600, 10, 0, true);
- $objects = find_active_users(600, 10);
+ $limit = max(0, (int) get_input("limit", 10));
+ $offset = max(0, (int) get_input("offset", 0));
+
+ $count = find_active_users(600, $limit, $offset, true);
+ $objects = find_active_users(600, $limit, $offset);
if ($objects) {
return elgg_view_entity_list($objects, array(
'count' => $count,
- 'limit' => 10,
+ 'limit' => $limit,
+ 'offset' => $offset
));
}
return '';
diff --git a/engine/lib/system_log.php b/engine/lib/system_log.php
index 5a153afb2..84302632e 100644
--- a/engine/lib/system_log.php
+++ b/engine/lib/system_log.php
@@ -187,7 +187,16 @@ function system_log($object, $event) {
$object_subtype = $object->getSubtype();
$event = sanitise_string($event);
$time = time();
- $ip_address = sanitise_string($_SERVER['REMOTE_ADDR']);
+
+ if (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) {
+ $ip_address = array_pop(explode(',', $_SERVER['HTTP_X_FORWARDED_FOR']));
+ } elseif (!empty($_SERVER['HTTP_X_REAL_IP'])) {
+ $ip_address = array_pop(explode(',', $_SERVER['HTTP_X_REAL_IP']));
+ } else {
+ $ip_address = $_SERVER['REMOTE_ADDR'];
+ }
+ $ip_address = sanitise_string($ip_address);
+
$performed_by = elgg_get_logged_in_user_guid();
if (isset($object->access_id)) {
diff --git a/engine/lib/upgrade.php b/engine/lib/upgrade.php
index 0cc1e64dc..158ec9ec1 100644
--- a/engine/lib/upgrade.php
+++ b/engine/lib/upgrade.php
@@ -245,7 +245,7 @@ function version_upgrade() {
// No version number? Oh snap...this is an upgrade from a clean installation < 1.7.
// Run all upgrades without error reporting and hope for the best.
- // See http://trac.elgg.org/elgg/ticket/1432 for more.
+ // See https://github.com/elgg/elgg/issues/1432 for more.
$quiet = !$dbversion;
// Note: Database upgrades are deprecated as of 1.8. Use code upgrades. See #1433
diff --git a/engine/lib/upgrades/2010033101.php b/engine/lib/upgrades/2010033101.php
index 0bffee001..4779295fd 100644
--- a/engine/lib/upgrades/2010033101.php
+++ b/engine/lib/upgrades/2010033101.php
@@ -1,7 +1,7 @@
<?php
/**
- * Conditional upgrade for UTF8 as described in http://trac.elgg.org/ticket/1928
+ * Conditional upgrade for UTF8 as described in https://github.com/elgg/elgg/issues/1928
*/
// get_version() returns the code version.
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
index 07732f261..780038c32 100644
--- 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
@@ -3,7 +3,7 @@
* Elgg 1.8.3 upgrade 2012041801
* multiple_user_tokens
*
- * Fixes http://trac.elgg.org/ticket/4291
+ * Fixes https://github.com/elgg/elgg/issues/4291
* Removes the unique index on users_apisessions for user_guid and site_guid
*/
diff --git a/engine/lib/upgrades/2013051700-1.8.15-add_missing_group_index-52a63a3a3ffaced2.php b/engine/lib/upgrades/2013051700-1.8.15-add_missing_group_index-52a63a3a3ffaced2.php
new file mode 100644
index 000000000..ee99bdbc8
--- /dev/null
+++ b/engine/lib/upgrades/2013051700-1.8.15-add_missing_group_index-52a63a3a3ffaced2.php
@@ -0,0 +1,28 @@
+<?php
+/**
+ * Elgg 1.8.15 upgrade 2013051700
+ * add_missing_group_index
+ *
+ * Some Elgg sites are missing the groups_entity full text index on name and
+ * description. This checks if it exists and adds it if it does not.
+ */
+
+$db_prefix = elgg_get_config('dbprefix');
+
+$full_text_index_exists = false;
+$results = get_data("SHOW INDEX FROM {$db_prefix}groups_entity");
+if ($results) {
+ foreach ($results as $result) {
+ if ($result->Index_type === 'FULLTEXT') {
+ $full_text_index_exists = true;
+ }
+ }
+}
+
+if ($full_text_index_exists == false) {
+ $query = "ALTER TABLE {$db_prefix}groups_entity
+ ADD FULLTEXT name_2 (name, description)";
+ if (!update_data($query)) {
+ elgg_log("Failed to add full text index to groups_entity table", 'ERROR');
+ }
+}
diff --git a/engine/lib/upgrades/2013052900-1.8.15-ipv6_in_syslog-f5c2cc0196e9e731.php b/engine/lib/upgrades/2013052900-1.8.15-ipv6_in_syslog-f5c2cc0196e9e731.php
new file mode 100644
index 000000000..d333a6cd2
--- /dev/null
+++ b/engine/lib/upgrades/2013052900-1.8.15-ipv6_in_syslog-f5c2cc0196e9e731.php
@@ -0,0 +1,12 @@
+<?php
+/**
+ * Elgg 1.8.15 upgrade 2013052900
+ * ipv6_in_syslog
+ *
+ * Upgrade the ip column in system_log to be able to store ipv6 addresses
+ */
+
+$db_prefix = elgg_get_config('dbprefix');
+$q = "ALTER TABLE {$db_prefix}system_log MODIFY COLUMN ip_address varchar(46) NOT NULL";
+
+update_data($q); \ No newline at end of file
diff --git a/engine/lib/upgrades/2013060900-1.8.15-site_secret-404fc165cf9e0ac9.php b/engine/lib/upgrades/2013060900-1.8.15-site_secret-404fc165cf9e0ac9.php
new file mode 100644
index 000000000..538d74dd6
--- /dev/null
+++ b/engine/lib/upgrades/2013060900-1.8.15-site_secret-404fc165cf9e0ac9.php
@@ -0,0 +1,16 @@
+<?php
+/**
+ * Elgg 1.8.15 upgrade 2013060900
+ * site_secret
+ *
+ * Description
+ */
+
+$strength = _elgg_get_site_secret_strength();
+
+if ($strength !== 'strong') {
+ // a new key is needed immediately
+ register_translations(elgg_get_root_path() . 'languages/');
+
+ elgg_add_admin_notice('weak_site_key', elgg_echo("upgrade:site_secret_warning:$strength"));
+}
diff --git a/engine/lib/users.php b/engine/lib/users.php
index 9a5194896..a8fb9121c 100644
--- a/engine/lib/users.php
+++ b/engine/lib/users.php
@@ -553,6 +553,11 @@ function get_user($guid) {
function get_user_by_username($username) {
global $CONFIG, $USERNAME_TO_GUID_MAP_CACHE;
+ // Fixes #6052. Username is frequently sniffed from the path info, which,
+ // unlike $_GET, is not URL decoded. If the username was not URL encoded,
+ // this is harmless.
+ $username = rawurldecode($username);
+
$username = sanitise_string($username);
$access = get_access_sql_suffix('e');
@@ -1091,6 +1096,7 @@ function friends_page_handler($segments, $handler) {
* @access private
*/
function collections_page_handler($page_elements) {
+ gatekeeper();
elgg_set_context('friends');
$base = elgg_get_config('path');
if (isset($page_elements[0])) {
diff --git a/engine/lib/views.php b/engine/lib/views.php
index c4b349fc6..1142461fe 100644
--- a/engine/lib/views.php
+++ b/engine/lib/views.php
@@ -218,7 +218,7 @@ function elgg_register_ajax_view($view) {
/**
* Unregister a view for ajax calls
- *
+ *
* @param string $view The view name
* @return void
* @since 1.8.3
@@ -369,7 +369,7 @@ function elgg_view_exists($view, $viewtype = '', $recurse = true) {
* view, $view_name plugin hook.
*
* @warning Any variables in $_SESSION will override passed vars
- * upon name collision. See {@trac #2124}.
+ * upon name collision. See https://github.com/Elgg/Elgg/issues/2124
*
* @param string $view The name and location of the view to use
* @param array $vars Variables to pass to the view.
@@ -795,7 +795,7 @@ function elgg_view_menu($menu_name, array $vars = array()) {
* - bool 'full_view' Whether to show a full or condensed view.
*
* @tip This function can automatically appends annotations to entities if in full
- * view and a handler is registered for the entity:annotate. See {@trac 964} and
+ * view and a handler is registered for the entity:annotate. See https://github.com/Elgg/Elgg/issues/964 and
* {@link elgg_view_entity_annotations()}.
*
* @param ElggEntity $entity The entity to display
@@ -992,6 +992,11 @@ function elgg_view_annotation(ElggAnnotation $annotation, array $vars = array(),
function elgg_view_entity_list($entities, $vars = array(), $offset = 0, $limit = 10, $full_view = true,
$list_type_toggle = true, $pagination = true) {
+ if (!$vars["limit"] && !$vars["offset"]) {
+ // no need for pagination if listing is unlimited
+ $vars["pagination"] = false;
+ }
+
if (!is_int($offset)) {
$offset = (int)get_input('offset', 0);
}
@@ -1064,8 +1069,13 @@ function elgg_view_annotation_list($annotations, array $vars = array()) {
'full_view' => true,
'offset_key' => 'annoff',
);
-
+
$vars = array_merge($defaults, $vars);
+
+ if (!$vars["limit"] && !$vars["offset"]) {
+ // no need for pagination if listing is unlimited
+ $vars["pagination"] = false;
+ }
return elgg_view('page/components/list', $vars);
}
@@ -1239,7 +1249,7 @@ function elgg_view_river_item($item, array $vars = array()) {
// @todo this needs to be cleaned up
// Don't hide objects in closed groups that a user can see.
- // see http://trac.elgg.org/ticket/4789
+ // see https://github.com/elgg/elgg/issues/4789
// else {
// // hide based on object's container
// $visibility = ElggGroupItemVisibility::factory($object->container_guid);
@@ -1334,12 +1344,12 @@ function elgg_view_list_item($item, array $vars = array()) {
/**
* View one of the elgg sprite icons
- *
+ *
* Shorthand for <span class="elgg-icon elgg-icon-$name"></span>
- *
+ *
* @param string $name The specific icon to display
* @param string $class Additional class: float, float-alt, or custom class
- *
+ *
* @return string The html for displaying an icon
*/
function elgg_view_icon($name, $class = '') {
@@ -1550,7 +1560,7 @@ function autoregister_views($view_base, $folder, $base_location_path, $viewtype)
function elgg_views_add_rss_link() {
global $autofeed;
if (isset($autofeed) && $autofeed == true) {
- $url = full_url();
+ $url = current_page_url();
if (substr_count($url, '?')) {
$url .= "&view=rss";
} else {
@@ -1638,7 +1648,7 @@ function elgg_views_boot() {
}
// set default icon sizes - can be overridden in settings.php or with plugin
- if (!$CONFIG->icon_sizes) {
+ if (!isset($CONFIG->icon_sizes)) {
$icon_sizes = array(
'topbar' => array('w' => 16, 'h' => 16, 'square' => TRUE, 'upscale' => TRUE),
'tiny' => array('w' => 25, 'h' => 25, 'square' => TRUE, 'upscale' => TRUE),
diff --git a/engine/lib/web_services.php b/engine/lib/web_services.php
index b440e3afb..51cad6f39 100644
--- a/engine/lib/web_services.php
+++ b/engine/lib/web_services.php
@@ -1166,6 +1166,17 @@ function list_all_apis() {
* @access private
*/
function auth_gettoken($username, $password) {
+ // check if username is an email address
+ if (is_email_address($username)) {
+ $users = get_user_by_email($username);
+
+ // check if we have a unique user
+ if (is_array($users) && (count($users) == 1)) {
+ $username = $users[0]->username;
+ }
+ }
+
+ // validate username and password
if (true === elgg_authenticate($username, $password)) {
$token = create_user_token($username);
if ($token) {
@@ -1195,7 +1206,7 @@ $ERRORS = array();
*
* @return void
* @access private
- *
+ *
* @throws Exception
*/
function _php_api_error_handler($errno, $errmsg, $filename, $linenum, $vars) {