function __construct() { $sa = LG_STANDALONE ? ' (standalone)' : ''; $ip = $_SERVER['REMOTE_ADDR']; lgDebug("Request started for {$ip}{$sa}: " . join(',', array_keys($_REQUEST))); // Make singleton available if we need it self::$instance = $this; // Check that the local distributed database table exists and has a matching structure $this->checkTable(); // Delete any objects that have reached their expiry time $this->expire(); // Instantiate the main global objects LigminchaGlobalServer::getMaster(); $server = LigminchaGlobalServer::getCurrent(); LigminchaGlobalUser::checkAll(); LigminchaGlobalSSO::makeSessionFromCookie(); // If this is a changes request, if (array_key_exists(self::$cmd, $_REQUEST)) { // Commit the data (and re-route if master) $data = $_REQUEST[self::$cmd]; if ($data) { print self::recvQueue($data); } elseif ($server->isMaster) { print self::encodeData($this->initialTableData()); } // If we're the master, always send queue incase any re-routing if ($server->isMaster) { self::sendQueue(); } exit; } elseif ($server->isMaster && array_key_exists('fakeinfo', $_REQUEST)) { $actions = array('edited', 'created', 'booked', 'posted'); $titles = array('Alguma Coisa', 'Outra Coisa', 'Muitas Coisas', 'Mais ou Menos'); $users = LigminchaGlobalUser::select(); $user = $users[rand(0, count($users) - 1)]->data['realname']; $action = $actions[rand(0, count($actions) - 1)]; $title = $titles[rand(0, count($titles) - 1)]; new LigminchaGlobalLog("{$user} {$action} {$title}", 'Info', time() + 1000); self::sendToWebSocket(array(0, $server->id, 0, LigminchaGlobalSync::select()[0]), 0); self::sendQueue(); exit; } }
/** * Get/create current session instance */ public static function getCurrent() { $update = false; if (is_null(self::$current)) { // If there's a current user, get/make a current session if (LigminchaGlobalUser::getCurrent()) { // None found, create new // - there will already be a current session established if one existed thanks to SSO::makeSessionFromCookie self::$current = new LigminchaGlobalSession(); // Doesn't exist, make the data structure for our new server object self::$current->ref1 = LigminchaGlobalServer::getCurrent()->id; self::$current->tag = self::getBrowser(); // Session only lives for five seconds in this initial form and doesn't route self::$current->expire = self::timestamp() + 2; self::$current->flag(LG_LOCAL, true); self::$current->flag(LG_PRIVATE, true); // Save our new instance to the DB $update = true; // And save the ID in the SSO cookie LigminchaGlobalSSO::setCookie(self::$current->id); lgDebug('New session created and SSO cookie set', self::$current); } else { self::$current = false; } } // Update the expiry if the session existed (but only if it's increasing by more than a minute to avoid sync traffic) if (self::$current && !self::$current->flag(LG_NEW)) { $expiry = self::timestamp() + LG_SESSION_DURATION; if ($expiry - self::$current->expire > 60) { self::$current->expire = $expiry; $update = true; } } // Avoid multiple calls to update above if ($update) { self::$current->update(); } return self::$current; }
/** * Make a current session and current user from an SSO session ID cookie (called when running on a master standalone site) */ public static function makeSessionFromCookie() { if (array_key_exists(self::$cookie, $_COOKIE)) { if ($session = LigminchaGlobalSession::selectOne(array('id' => $_COOKIE[self::$cookie]))) { if ($user = LigminchaGlobalUser::newFromId($session->owner)) { LigminchaGlobalSession::setCurrent($session); LigminchaGlobalUser::setCurrent($user); lgDebug('Session established from existing SSO cookie', $session); } else { lgDebug('SSO session cookie found, but user is no longer logged in (' . substr($_COOKIE[self::$cookie], 0, 5) . ')'); } } else { lgDebug('SSO session cookie found, but not in database (' . substr($_COOKIE[self::$cookie], 0, 5) . ')'); } if (!$session || !$user) { if ($session) { LigminchaGlobalDistributed::del(array('id' => $session->id)); } self::delCookie(); } } else { lgDebug('No SSO session cookie found ' . var_export($_COOKIE, true)); } }
/** * This is used from standalone context to set the session from the SSO cookie */ public static function setCurrent($user) { self::$current = $user; }
/** * Update or create an object in the database and queue the changes if necessary * - $origin is passed if this changed arrived from a remote queue * - $silent is used to stop any sync objects being generated by the change */ public function update($origin = false, $silent = false) { $db = JFactory::getDbo(); $table = LigminchaGlobalDistributed::sqlTable(); // Bail if no type if ($this->type < 1) { die('Typeless distributed objects not allowed!'); } // Update an existing object in the database if ($this->exists) { // TODO: Validate cond // Update automatic properties $this->flag(LG_NEW, false); $this->modified = self::timestamp(); $sqlVals = $this->sqlValues(false); lgDebug('Updating database, object: ' . $this->id); $db->setQuery("UPDATE {$table} SET {$sqlVals} WHERE `id`=0x{$this->id}"); $db->query(); } else { // Only set the automatic properties for locally created non-existent objects if (!$origin) { $this->flag(LG_NEW, true); $this->modified = null; $this->creation = self::timestamp(); // The entry is owned by the user unless it's a server/sync/user object if ($this->type == LG_SERVER || $this->type == LG_USER || $this->type == LG_SYNC) { $this->owner = null; } else { $this->owner = LigminchaGlobalUser::getCurrent() ? LigminchaGlobalUser::getCurrent()->id : null; } } $sqlVals = $this->sqlValues(); $db->setQuery("REPLACE INTO {$table} SET {$sqlVals}"); $db->query(); } // Add outgoing sync objects depending on the context of this change // TODO: $private = $this->flag( LG_PRIVATE ) ? $this->owner->server : false if (!$silent && !$this->flag(LG_LOCAL)) { LigminchaGlobalSync::create('U', $this->fields(), $origin, $private = false); } }