/** * Adds a device to the system, after sending a test notification to it * @param {array} $device * @param {string} $device.userId * @param {string} $device.deviceId * @param {string} [$device.formFactor] * @param {string} [$device.platform] * @param {string} [$device.version] * @param {string} [$device.sessionId] * @param {boolean} [$device.sandbox] * @param {string} [$device.passphrase] * @param {boolean} [$skipNotification=false] if true, skips sending notification * @return {Users_Device} */ static function add($device, $skipNotification = false) { Q_Valid::requireFields(array('userId', 'deviceId'), $device, true); $userId = $device['userId']; $deviceId = $device['deviceId']; if (!$skipNotification) { $app = Q::app(); $sandbox = Q::ifset($device, 'sandbox', null); if (!isset($sandbox)) { $sandbox = Q_Config::get($app, "cordova", "ios", "sandbox", false); } $env = $sandbox ? ApnsPHP_Abstract::ENVIRONMENT_SANDBOX : ApnsPHP_Abstract::ENVIRONMENT_PRODUCTION; $s = $sandbox ? 'sandbox' : 'production'; $cert = APP_LOCAL_DIR . DS . 'Users' . DS . 'certs' . DS . $app . DS . $s . DS . 'bundle.pem'; $authority = USERS_PLUGIN_FILES_DIR . DS . 'Users' . DS . 'certs' . DS . 'EntrustRootCA.pem'; $logger = new Users_ApnsPHP_Logger(); $push = new ApnsPHP_Push($env, $cert); $push->setLogger($logger); $push->setRootCertificationAuthority($authority); if (isset($device['passphrase'])) { $push->setProviderCertificatePassphrase($device['passphrase']); } $push->connect(); $message = new ApnsPHP_Message($deviceId); $message->setCustomIdentifier('Users_Device-adding'); $message->setBadge(0); $message->setText(Q_Config::get($app, "cordova", "ios", "device", "text", "Notifications have been enabled")); $message->setCustomProperty('userId', $userId); $message->setExpiry(5); $push->add($message); $push->send(); $push->disconnect(); $errors = $push->getErrors(); if (!empty($errors)) { $result = reset($errors); throw new Users_Exception_DeviceNotification($result['ERRORS'][0]); } } $sessionId = Q_Session::id(); $user = Users::loggedInUser(); $info = array_merge(Q_Request::userAgentInfo(), array('sessionId' => $sessionId, 'userId' => $user ? $user->id : null, 'deviceId' => null)); $device2 = Q::take($device, $info); $d = new Users_Device($device2); $d->save(true); if ($sessionId) { $s = new Users_Session(); $s->id = $sessionId; if (!$s->retrieve()) { $s->deviceId = $deviceId; } } $_SESSION['Users']['deviceId'] = $deviceId; $device2['Q/method'] = 'Users/device'; Q_Utils::sendToNode($device2); return $d; }
function Users_before_Q_responseExtras() { Q_Response::addScript('plugins/Users/js/Users.js'); $app = Q_Config::expect('Q', 'app'); $requireLogin = Q_Config::get('Users', 'requireLogin', array()); $rl_array = array(); foreach ($requireLogin as $rl => $value) { $rl_array[Q_Uri::url($rl)] = $value; } if (!Q_Request::isAjax()) { Q_Response::setScriptData('Q.plugins.Users.requireLogin', $rl_array); $successUrl = Q_Config::get('Users', 'uris', "{$app}/successUrl", "{$app}/home"); $afterActivate = Q_Config::get('Users', 'uris', "{$app}/afterActivate", $successUrl); $loginOptions = Q_Config::get('Users', 'login', array("identifierType" => 'email,mobile', "userQueryUri" => 'Users/user', "using" => "native,facebook", "noRegister" => false)); $loginOptions["afterActivate"] = Q_Uri::url($afterActivate); $loginOptions["successUrl"] = Q_Uri::url($successUrl); Q_Response::setScriptData('Q.plugins.Users.login.serverOptions', $loginOptions); $setIdentifierOptions = Q::take($loginOptions, array('identifierType')); Q_Response::setScriptData('Q.plugins.Users.setIdentifier.serverOptions', $setIdentifierOptions); } $fb_app_info = Q_Config::get('Users', 'facebookApps', $app, array()); if ($fb_app_info) { unset($fb_app_info['secret']); Q_Response::setScriptData("Q.plugins.Users.facebookApps.{$app}", $fb_app_info); } if ($node_server_url = Q_Config::get('Users', 'nodeServer', 'url', null)) { Q_Response::setScriptData("Q.plugins.Users.nodeServer", parse_url($node_server_url)); } if (Q_Config::get('Users', 'showLoggedInUser', true)) { $user = Q_Session::id() ? Users::loggedInUser() : null; if ($user) { $u = $user->exportArray(); $u['sessionCount'] = $user->sessionCount; Q_Response::setScriptData("Q.plugins.Users.loggedInUser", $u); Q_Response::addScriptLine("Q.plugins.Users.loggedInUser = new Q.plugins.Users.User(Q.plugins.Users.loggedInUser);"); } } Q_Response::setScriptData('Q.plugins.Users.communityId', Users::communityId()); Q_Response::setScriptData('Q.plugins.Users.communityName', Users::communityName()); Q_Response::setScriptData('Q.plugins.Users.communitySuffix', Users::communitySuffix()); Q_Response::setScriptData('Q.plugins.Users.hinted', Q::ifset($_SESSION, 'Users', 'hinted', array())); if ($sizes = Q_Config::expect('Users', 'icon', 'sizes')) { sort($sizes); Q_Response::setScriptData('Q.plugins.Users.icon.sizes', $sizes); } $defaultSize = Q_Config::get('Users', 'icon', 'defaultSize', 40); Q_Response::setScriptData('Q.plugins.Users.icon.defaultSize', $defaultSize); Q_Response::addStylesheet("plugins/Users/css/Users.css"); }
function Users_before_Q_response_notices() { $from_parts = explode(' ', Q_Request::special('fromSuccess', false)); $from = reset($from_parts); if ($from === 'Users/activate') { $user = Q_Session::id() ? Users::loggedInUser() : null; $notice = $user ? "You've completed the activation." : "You've completed the activation. Try logging in now."; Q_Response::setNotice('Users/activate', $notice, true); } else { if ($from === 'Users/resend') { $notice = 'Your activation message has been re-sent. You should get it in a moment.'; Q_Response::setNotice('Users/resend', $notice, true); } } }
function Users_device_post() { $user = Users::loggedInUser(true); $token = isset($_REQUEST['token']) ? $_REQUEST['token'] : null; $platform = Q_Request::platform(); $version = Q_Request::OSVersion(); $formFactor = Q_Request::isMobile() ? 'mobile' : (Q_Request::isTablet() ? 'tablet' : null); $device = new Users_Device(); $device->userId = $user->id; $device->deviceId = $token; $device->platform = $platform; $device->version = $version; $device->formFactor = $formFactor; $device->sessionId = Q_Session::id(); $_SESSION['Users']['deviceId'] = $token; Q_Response::setSlot('data', !!$device->save(true)); Q_Utils::sendToNode(array("Q/method" => "Users/device", "userId" => $user->id, "deviceId" => $token)); }
function Users_oAuth_post() { // Validate the inputs $fields = array('response_type', 'token_type', 'access_token', 'expires_in', 'scope', 'state', 'Q_Users_oAuth'); Q_Request::requireFields($fields, true); $params = Q::take($_REQUEST, $fields); $params['Q.Users.oAuth'] = $params['Q_Users_oAuth']; unset($params['Q_Users_oAuth']); Q_Valid::signature(true, $params, array('Q.Users.oAuth')); // Set the session id to the access_token Q_Session::id($params['access_token']); // Add a device, if any if ($deviceId = Q::ifset($_REQUEST, 'deviceId', null)) { $fields2 = array('deviceId', 'platform', 'version', 'formFactor'); Q_Request::requireFields($fields2); $device = Q::take($_REQUEST, $fields2); $device['userId'] = Users::loggedInUser(true)->id; Users_Device::add($device); } }
function Users_after_Q_session_write($params) { Q::$state['session'] = true; if (!$params['changed']) { return; } // Q::autoload('Db'); // Q::autoload('Db_Mysql'); // Q::autoload('Db_Result'); // Q::autoload('Db_Expression'); // Q::autoload('Db_Query'); // Q::autoload('Db_Query_Mysql'); // Q::autoload('Db_Row'); // Q::autoload('Base_Users_Session'); // Q::autoload('Base_Users'); // Q::autoload('Users'); Q::autoload('Q_Utils'); Q::autoload('Q_Config'); Q::autoload('Q_Session'); $id = Q_Session::id(); if (!$id) { return; } $parts = explode('-', $id); $duration = count($parts) > 1 ? $parts[0] : 0; $content = Q::json_encode($_SESSION, JSON_FORCE_OBJECT); if (Users::$loggedOut) { Q_Utils::sendToNode(array("Q/method" => "Users/session", "sessionId" => $id, "content" => null, "duration" => $duration)); } else { if (Q_Session::id() and !empty($_SERVER['HTTP_HOST'])) { try { Q_Utils::sendToNode(array("Q/method" => "Users/session", "sessionId" => $id, "content" => $content, "duration" => $duration)); } catch (Exception $e) { // don't throw here, it would only result in a mysterious fatal error } } } }
function Users_after_Q_session_destroy($params) { Q::$state['session'] = true; // Q::autoload('Db'); // Q::autoload('Db_Mysql'); // Q::autoload('Db_Result'); // Q::autoload('Db_Expression'); // Q::autoload('Db_Query'); // Q::autoload('Db_Query_Mysql'); // Q::autoload('Db_Row'); // Q::autoload('Base_Users_Session'); // Q::autoload('Base_Users'); // Q::autoload('Users'); Q::autoload('Q_Utils'); Q::autoload('Q_Config'); Q::autoload('Q_Session'); $id = Q_Session::id(); if (!$id) { return; } $content = Q::json_encode($_SESSION, JSON_FORCE_OBJECT); Q_Utils::sendToNode(array("Q/method" => "Users/session", "sessionId" => $id, "content" => null, "updatedTime" => null, "destroyed" => true)); }
/** * Saves a new Users_Session row with a copy of all the content from the current session. * @param {string|integer} $duration The key in the Q / session / durations config field or number of seconds * @return {string} the id of the new session */ static function copyToNewSession($duration = 'year') { $id = Q_Session::id(); if (!$id) { return null; } $seconds = is_string($duration) ? Q_Config::expect('Q', 'session', 'durations', $duration) : $duration; session_write_close(); // close current session $us = new Users_Session(); $us->id = $id; $us->retrieve(null, null, array('lock' => 'FOR UPDATE')); $us2 = new Users_Session(); if ($us->wasRetrieved()) { $us2->copyFromRow($us, null, false, true); $us2->wasRetrieved(false); } else { $us2->content = "{}"; $us2->php = ""; $us2->deviceId = ""; $us2->timeout = 0; } $us2->id = Q_Session::generateId(); $us2->duration = $seconds; $us2->save(false, true); $new_id = $us2->id; session_start(); // reopen current session Q::event("Users/copyToNewSession", array('duration' => $duration, 'from_sessionId' => $id, 'to_sessionId' => $us2->id), 'after'); return $us2->id; }
/** * @method shutdownFunction * @static */ static function shutdownFunction() { if ($error = error_get_last()) { Q::log($error, 'fatal'); header('PHP Fatal Error', true, 500); // do not expose the error contents } /** * @event Q/shutdown {before} */ Q::event('Q/shutdown', compact('error'), 'before'); Q_Cache::shutdownFunction(); if (Q_Session::id()) { session_write_close(); } }
/** * Removes a notice * @method removeNotice * @static * @param {string} $key * @return {boolean} true if notice has been deleted, false otherwise */ static function removeNotice($key) { if (!isset(self::$notices[$key])) { return false; } unset(self::$notices[$key]); if (Q_Session::id()) { unset($_SESSION['Q']['notices'][$key]); } self::$removedNotices[$key] = true; return true; }
/** * @method start * @static * @return {boolean} */ static function start() { if (self::id()) { // Session has already started return false; } /** * @event Q/session/start {before} * @return {false} * Return false to cancel session start */ if (false === Q::event('Q/session/start', array(), 'before')) { return false; } if (Q_Config::get('Q', 'session', 'custom', true)) { session_set_save_handler(array(__CLASS__, 'openHandler'), array(__CLASS__, 'closeHandler'), array(__CLASS__, 'readHandler'), array(__CLASS__, 'writeHandler'), array(__CLASS__, 'destroyHandler'), array(__CLASS__, 'gcHandler')); } if (!empty($_SESSION)) { $pre_SESSION = $_SESSION; } self::init(); $name = Q_Session::name(); $id = isset($_REQUEST[$name]) ? $_REQUEST[$name] : isset($_COOKIE[$name]) ? $_COOKIE[$name] : null; if (!self::isValidId($id)) { // The session id was probably not generated by us, generate a new one /** * @event Q/session/generate {before} * @param {string} id An invalid id, if any, that was passed by the client * @return {boolean} */ if (false === Q::event('Q/session/generate', compact('id'), 'before')) { return false; } $id = self::generateId(); } try { if ($id) { self::processDbInfo(); if (self::$session_db_connection) { $id_field = self::$session_db_id_field; $data_field = self::$session_db_data_field; $updated_field = self::$session_db_updated_field; $duration_field = self::$session_db_duration_field; $class = self::$session_db_row_class; $row = new $class(); $row->{$id_field} = $id; if ($row->retrieve()) { self::$session_db_row = $row; } else { // Start a new session with our own id $id = $row->{$id_field} = self::generateId(); $row->{$data_field} = ""; $row->{$updated_field} = date('Y-m-d H:i:s'); $row->{$duration_field} = Q_Config::get('Q', 'session', 'durations', Q_Request::formFactor(), Q_Config::expect('Q', 'session', 'durations', 'session')); if (false !== Q::event('Q/session/save', array('row' => $row, 'id_field' => $id_field, 'data_field' => $data_field, 'updated_field' => $updated_field, 'duration_field' => $duration_field, 'inserting' => true), 'before')) { $row->save(); self::id($row->{$id_field}); // this sets the session cookie as well self::$session_db_row = $row; } } } self::id($id); } if (!empty($_SERVER['HTTP_HOST'])) { $durationName = self::durationName(); $duration = Q_Config::get('Q', 'session', 'durations', $durationName, 0); Q_Response::setCookie(self::name(), $id, $duration ? time() + $duration : 0); } else { if (empty($_SESSION)) { $_SESSION = array(); } } ini_set('session.use_cookies', 0); // we are gonna handle the cookies, thanks session_cache_limiter(''); // don't send the cache limiter headers either session_start(); } catch (Exception $e) { $app = Q_Config::get('Q', 'app', null); $prefix = $app ? "{$app}/" : ''; if (empty($_SERVER['HTTP_HOST'])) { echo "Warning: Ignoring Q_Session::start() called before running {$prefix}scripts/Q/install.php --all" . PHP_EOL; $message = $e->getMessage(); $file = $e->getFile(); $line = $e->getLine(); if (is_callable(array($e, 'getTraceAsStringEx'))) { $trace_string = $e->getTraceAsStringEx(); } else { $trace_string = $e->getTraceAsString(); } echo "{$message}\n(in {$file} line {$line})\n{$trace_string}" . PHP_EOL; } else { if (is_callable('apc_clear_cache')) { apc_clear_cache('user'); } Q::log($e); throw new Q_Exception("Please run {$prefix}scripts/Q/install.php --all"); } } // merge in all the stuff that was added to $_SESSION // before we started it. if (isset($pre_SESSION)) { foreach ($pre_SESSION as $k => $v) { $_SESSION[$k] = $v; } } if (isset($_SESSION['Q']['notices'])) { foreach ($_SESSION['Q']['notices'] as $k => $v) { Q_Response::setNotice($k, $v); } } if (!empty($_SESSION['Q']['terminated'])) { throw new Q_Exception_SessionTerminated(array('id' => Q_Session::id())); } if (Q_Config::get('Q', 'session', 'userAgentInfo', null)) { $arr = isset($_SESSION['Q']) ? $_SESSION['Q'] : array(); $_SESSION['Q'] = array_merge($arr, Q_Request::userAgentInfo()); } /** * @event Q/session/start {after} */ Q::event('Q/session/start', array(), 'after'); return true; }