123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335 |
- <?php
- /**
- * Elgg system log.
- * Listens to events and writes crud events into the system log database.
- *
- * @package Elgg.Core
- * @subpackage Logging
- */
- /**
- * Retrieve the system log based on a number of parameters.
- *
- * @todo too many args, and the first arg is too confusing
- *
- * @param int|array $by_user The guid(s) of the user(s) who initiated the event.
- * Use 0 for unowned entries. Anything else falsey means anyone.
- * @param string $event The event you are searching on.
- * @param string $class The class of object it effects.
- * @param string $type The type
- * @param string $subtype The subtype.
- * @param int $limit Maximum number of responses to return. (default from settings)
- * @param int $offset Offset of where to start.
- * @param bool $count Return count or not
- * @param int $timebefore Lower time limit
- * @param int $timeafter Upper time limit
- * @param int $object_id GUID of an object
- * @param string $ip_address The IP address.
- * @return mixed
- */
- function get_system_log($by_user = "", $event = "", $class = "", $type = "", $subtype = "", $limit = null,
- $offset = 0, $count = false, $timebefore = 0, $timeafter = 0, $object_id = 0,
- $ip_address = "") {
- global $CONFIG;
- $by_user_orig = $by_user;
- if (is_array($by_user) && sizeof($by_user) > 0) {
- foreach ($by_user as $key => $val) {
- $by_user[$key] = (int) $val;
- }
- } else {
- $by_user = (int)$by_user;
- }
-
- $event = sanitise_string($event);
- $class = sanitise_string($class);
- $type = sanitise_string($type);
- $subtype = sanitise_string($subtype);
- $ip_address = sanitise_string($ip_address);
- if ($limit === null) {
- $limit = elgg_get_config('default_limit');
- }
- $limit = (int)$limit;
- $offset = (int)$offset;
- $where = array();
- if ($by_user_orig !== "" && $by_user_orig !== false && $by_user_orig !== null) {
- if (is_int($by_user)) {
- $where[] = "performed_by_guid=$by_user";
- } else if (is_array($by_user)) {
- $where [] = "performed_by_guid in (" . implode(",", $by_user) . ")";
- }
- }
- if ($event != "") {
- $where[] = "event='$event'";
- }
- if ($class !== "") {
- $where[] = "object_class='$class'";
- }
- if ($type != "") {
- $where[] = "object_type='$type'";
- }
- if ($subtype !== "") {
- $where[] = "object_subtype='$subtype'";
- }
- if ($timebefore) {
- $where[] = "time_created < " . ((int) $timebefore);
- }
- if ($timeafter) {
- $where[] = "time_created > " . ((int) $timeafter);
- }
- if ($object_id) {
- $where[] = "object_id = " . ((int) $object_id);
- }
- if ($ip_address) {
- $where[] = "ip_address = '$ip_address'";
- }
- $select = "*";
- if ($count) {
- $select = "count(*) as count";
- }
- $query = "SELECT $select from {$CONFIG->dbprefix}system_log where 1 ";
- foreach ($where as $w) {
- $query .= " and $w";
- }
- if (!$count) {
- $query .= " order by time_created desc";
- $query .= " limit $offset, $limit"; // Add order and limit
- }
- if ($count) {
- $numrows = get_data_row($query);
- if ($numrows) {
- return $numrows->count;
- }
- } else {
- return get_data($query);
- }
- return false;
- }
- /**
- * Return a specific log entry.
- *
- * @param int $entry_id The log entry
- *
- * @return mixed
- */
- function get_log_entry($entry_id) {
- global $CONFIG;
- $entry_id = (int)$entry_id;
- return get_data_row("SELECT * from {$CONFIG->dbprefix}system_log where id=$entry_id");
- }
- /**
- * Return the object referred to by a given log entry
- *
- * @param \stdClass|int $entry The log entry row or its ID
- *
- * @return mixed
- */
- function get_object_from_log_entry($entry) {
- if (is_numeric($entry)) {
- $entry = get_log_entry($entry);
- if (!$entry) {
- return false;
- }
- }
- $class = $entry->object_class;
- $id = $entry->object_id;
- if (!class_exists($class)) {
- // failed autoload
- return false;
- }
- $getters = array(
- 'ElggAnnotation' => 'elgg_get_annotation_from_id',
- 'ElggMetadata' => 'elgg_get_metadata_from_id',
- 'ElggRelationship' => 'get_relationship',
- );
- if (isset($getters[$class]) && is_callable($getters[$class])) {
- $object = call_user_func($getters[$class], $id);
- } elseif (preg_match('~^Elgg[A-Z]~', $class)) {
- $object = get_entity($id);
- } else {
- // surround with try/catch because object could be disabled
- try {
- $object = new $class($entry->object_id);
- return $object;
- } catch (Exception $e) {
-
- }
- }
- if (!is_object($object) || get_class($object) !== $class) {
- return false;
- }
- return $object;
- }
- /**
- * Log a system event related to a specific object.
- *
- * This is called by the event system and should not be called directly.
- *
- * @param object $object The object you're talking about.
- * @param string $event The event being logged
- * @return void
- */
- function system_log($object, $event) {
- global $CONFIG;
- static $log_cache;
- static $cache_size = 0;
- if ($object instanceof Loggable) {
- /* @var \ElggEntity|\ElggExtender $object */
- if (datalist_get('version') < 2012012000) {
- // this is a site that doesn't have the ip_address column yet
- return;
- }
- // reset cache if it has grown too large
- if (!is_array($log_cache) || $cache_size > 500) {
- $log_cache = array();
- $cache_size = 0;
- }
- // Has loggable interface, extract the necessary information and store
- $object_id = (int)$object->getSystemLogID();
- $object_class = get_class($object);
- $object_type = $object->getType();
- $object_subtype = $object->getSubtype();
- $event = sanitise_string($event);
- $time = time();
- $ip_address = sanitize_string(_elgg_services()->request->getClientIp());
- if (!$ip_address) {
- $ip_address = '0.0.0.0';
- }
- $performed_by = elgg_get_logged_in_user_guid();
- if (isset($object->access_id)) {
- $access_id = $object->access_id;
- } else {
- $access_id = ACCESS_PUBLIC;
- }
- if (isset($object->enabled)) {
- $enabled = $object->enabled;
- } else {
- $enabled = 'yes';
- }
- if (isset($object->owner_guid)) {
- $owner_guid = $object->owner_guid;
- } else {
- $owner_guid = 0;
- }
- // Create log if we haven't already created it
- if (!isset($log_cache[$time][$object_id][$event])) {
- $query = "INSERT DELAYED into {$CONFIG->dbprefix}system_log
- (object_id, object_class, object_type, object_subtype, event,
- performed_by_guid, owner_guid, access_id, enabled, time_created, ip_address)
- VALUES
- ('$object_id','$object_class','$object_type', '$object_subtype', '$event',
- $performed_by, $owner_guid, $access_id, '$enabled', '$time', '$ip_address')";
- insert_data($query);
- $log_cache[$time][$object_id][$event] = true;
- $cache_size += 1;
- }
- }
- }
- /**
- * This function creates an archive copy of the system log.
- *
- * @param int $offset An offset in seconds from now to archive (useful for log rotation)
- *
- * @return bool
- */
- function archive_log($offset = 0) {
- global $CONFIG;
- $offset = (int)$offset;
- $now = time(); // Take a snapshot of now
- $ts = $now - $offset;
- // create table
- $query = "CREATE TABLE {$CONFIG->dbprefix}system_log_$now as
- SELECT * from {$CONFIG->dbprefix}system_log WHERE time_created<$ts";
- if (!update_data($query)) {
- return false;
- }
- // delete
- // Don't delete on time since we are running in a concurrent environment
- if (delete_data("DELETE from {$CONFIG->dbprefix}system_log WHERE time_created<$ts") === false) {
- return false;
- }
- // alter table to engine
- if (!update_data("ALTER TABLE {$CONFIG->dbprefix}system_log_$now engine=archive")) {
- return false;
- }
- return true;
- }
- /**
- * Default system log handler, allows plugins to override, extend or disable logging.
- *
- * @param string $event Event name
- * @param string $object_type Object type
- * @param Loggable $object Object to log
- *
- * @return true
- */
- function system_log_default_logger($event, $object_type, $object) {
- system_log($object['object'], $object['event']);
- return true;
- }
- /**
- * System log listener.
- * This function listens to all events in the system and logs anything appropriate.
- *
- * @param String $event Event name
- * @param String $object_type Type of object
- * @param Loggable $object Object to log
- *
- * @return true
- * @access private
- */
- function system_log_listener($event, $object_type, $object) {
- if (($object_type != 'systemlog') && ($event != 'log')) {
- elgg_trigger_event('log', 'systemlog', array('object' => $object, 'event' => $event));
- }
- return true;
- }
- return function(\Elgg\EventsService $events, \Elgg\HooksRegistrationService $hooks) {
- /** Register event to listen to all events **/
- $events->registerHandler('all', 'all', 'system_log_listener', 400);
- /** Register a default system log handler */
- $events->registerHandler('log', 'systemlog', 'system_log_default_logger', 999);
- };
|