/** * Used to post messages to EXISTING stream * $_REQUEST shall contain the content of the message. Also may include 'streamNames' * field which is an array of additional names of the streams to post message to. * * @param string $params * publisher id and stream name of existing stream shall be supplied * @return {void} */ function Streams_message_post() { $user = Users::loggedInUser(true); $publisherId = Streams::requestedPublisherId(true); $streamName = Streams::requestedName(true); // check if type is allowed $streams = Streams::fetch($user->id, $publisherId, $streamName); if (empty($streams)) { throw new Streams_Exception_NoSuchStream(); } $stream = reset($streams); if (empty($_REQUEST['type'])) { throw new Q_Exception_RequiredField(array('field' => 'type'), 'type'); } $type = $_REQUEST['type']; if (!Q_Config::get("Streams", "types", $stream->type, "messages", $type, 'post', false)) { throw new Q_Exception("This app doesn't support directly posting messages of type '{$type}' for streams of type '{$stream->type}'"); } $result = Streams_Message::post($user->id, $publisherId, $streamName, $_REQUEST); if (is_array($result)) { Streams::$cache['messages'] = $result; } else { Streams::$cache['message'] = $result; } }
/** * This tool renders a user avatar * * @param {array} $options An associative array of parameters, containing: * @param {boolean} [$options.userId] * "userId" => The user's id. Defaults to id of the logged-in user, if any. * @param {boolean} [$options.icon] * "icon" => Optional. Render icon before the username. * @param {boolean} [$options.iconAttributes] * "iconAttributes" => Optional. Array of attributes to render for the icon. * @param {boolean} [$options.editable] * "editable" => Optional. Whether to provide an interface for editing the user's info. Can be array containing "icon", "name". * @param {array} [$options.inplaces] Additional fields to pass to the child Streams/inplace tools, if any * @param {boolean} [$options.renderOnClient] * If true, only the html container is rendered, so the client will do the rest. */ function Users_avatar_tool($options) { $defaults = array('icon' => false, 'editable' => false); $options = array_merge($defaults, $options); if (empty($options['userId'])) { $user = Users::loggedInUser(); $options['userId'] = $user->id; } else { $user = Users_User::fetch($options['userId']); } Q_Response::addStylesheet('plugins/Q/css/Q.css'); Q_Response::setToolOptions($options); if (!empty($options['renderOnClient'])) { return ''; } if (!$user) { return ''; } $user->addPreloaded(); $p = $options; $p['userId'] = $user->id; Q_Response::setToolOptions($p); $result = ''; $icon = $options['icon']; if ($icon) { if ($icon === true) { $icon = Q_Config::get('Users', 'icon', 'defaultSize', 40); } $attributes = isset($options['iconAttributes']) ? $options['iconAttributes'] : array(); $attributes['class'] = isset($attributes['class']) ? $attributes['class'] . ' Users_avatar_icon' : 'Users_avatar_icon'; $result .= Q_Html::img($user->iconUrl($icon), 'user icon', $attributes); } $result .= '<span class="Users_avatar_name">' . $user->username . '</span>'; return $result; }
function Users_user_response_data($params) { // Get Gravatar info // WARNING: INTERNET_REQUEST $hash = md5(strtolower(trim($identifier))); $thumbnailUrl = Q_Request::baseUrl() . "/action.php/Users/thumbnail?hash={$hash}&size=80&type=" . Q_Config::get('Users', 'login', 'iconType', 'wavatar'); $json = @file_get_contents("http://www.gravatar.com/{$hash}.json"); $result = json_decode($json, true); if ($result) { if ($type === 'email') { $result['emailExists'] = !empty($exists); } else { if ($type === 'mobile') { $result['mobileExists'] = !empty($exists); } } return $result; } // otherwise, return default $email_parts = explode('@', $identifier, 2); $result = array("entry" => array(array("id" => "571", "hash" => "357a20e8c56e69d6f9734d23ef9517e8", "requestHash" => "357a20e8c56e69d6f9734d23ef9517e8", "profileUrl" => "http://gravatar.com/test", "preferredUsername" => ucfirst($email_parts[0]), "thumbnailUrl" => $thumbnailUrl, "photos" => array(), "displayName" => "", "urls" => array()))); if ($type === 'email') { $result['emailExists'] = !empty($exists); } else { $result['mobileExists'] = !empty($exists); } if ($terms_label = Users::termsLabel('register')) { $result['termsLabel'] = $terms_label; } return $result; }
function Streams_invite_validate() { if (Q_Request::method() === 'PUT') { return; } if (Q_Request::method() !== 'GET') { Q_Valid::nonce(true); } $fields = array('publisherId', 'streamName'); if (Q_Request::method() === 'POST') { if (Q_Valid::requireFields($fields)) { return; } foreach ($fields as $f) { if (strlen(trim($_REQUEST[$f])) === 0) { Q_Response::addError(new Q_Exception("{$f} can't be empty", $f)); } } } if (isset($_REQUEST['fullName'])) { $length_min = Q_Config::get('Streams', 'inputs', 'fullName', 'lengthMin', 5); $length_max = Q_Config::get('Streams', 'inputs', 'fullName', 'lengthMax', 30); if (strlen($_REQUEST['fullName']) < $length_min) { throw new Q_Exception("A user's full name can't be that short.", 'fullName'); } if (strlen($_REQUEST['fullName']) > $length_max) { throw new Q_Exception("A user's full name can't be that long.", 'fullName'); } } }
function Users_user_validate() { Q_Valid::nonce(true); $type = isset($_REQUEST['identifierType']) ? $_REQUEST['identifierType'] : Q_Config::get("Users", "login", "identifierType", "email,mobile"); $parts = explode(',', $type); $accept_mobile = true; $expected = 'email address or mobile number'; $fields = array('emailAddress', 'mobileNumber', 'identifier'); if (count($parts) === 1) { if ($parts[0] === 'email') { $expected = 'email address'; $fields = array('emailAddress', 'identifier'); $accept_mobile = false; } else { if ($parts[0] === 'mobile') { $expected = 'mobile number'; $fields = array('mobileNumber', 'identifier'); } } } if (!isset($_REQUEST['identifier'])) { throw new Q_Exception("a valid {$expected} is required", $fields); } if (!Q_Valid::email($_REQUEST['identifier'])) { if (!$accept_mobile) { throw new Q_Exception("a valid {$expected} is required", $fields); } if (!Q_Valid::phone($_REQUEST['identifier'])) { throw new Q_Exception("a valid {$expected} is required", $fields); } } }
/** * Used by HTTP clients to upload a new file to the server * @class Q/file * @method post * @param {array} [$params] Parameters that can come from the request * @param {string} [$params.data] Required if $_FILES is empty. Base64-encoded image data URI - see RFC 2397 * @param {string} [$params.path="uploads"] parent path under web dir (see subpath) * @param {string} [$params.subpath=""] subpath that should follow the path, to save the image under * @param {string} [$params.name] override the name of the file, after the subpath */ function Q_file_post($params = null) { $p = $params ? $params : Q::take($_REQUEST, array('data', 'path', 'subpath')); if (!empty($_FILES)) { $file = reset($_FILES); if ($tmp = $file['tmp_name']) { if (empty($p['data'])) { $p['data'] = file_get_contents($tmp); $p['name'] = $file['name']; } unlink($tmp); } } else { if (empty($p['data'])) { throw new Q_Exception_RequiredField(array('field' => 'data'), 'data'); } $p['data'] = base64_decode(chunk_split(substr($p['data'], strpos($p['data'], ',') + 1))); } $timeLimit = Q_Config::get('Q', 'uploads', 'limits', 'file', 'time', 5 * 60 * 60); set_time_limit($timeLimit); // default is 5 min $data = Q_File::save($p); if (empty($params)) { Q_Response::setSlot('data', $data); } return $data; }
function Streams_before_Q_responseExtras() { Q_Response::addScript('plugins/Streams/js/Streams.js'); $host = Q_Config::get('Streams', 'node', 'host', Q_Config::get('Q', 'node', 'host', null)); $port = Q_Config::get('Streams', 'node', 'port', Q_Config::get('Q', 'node', 'port', null)); $user = Users::loggedInUser(); if ($user) { Q_Response::setScriptData('Q.plugins.Users.loggedInUser.displayName', Streams::displayName($user)); } if (!Q_Request::isAjax()) { $invite_url = Q_Config::get('Streams', 'invite', 'url', "http://invites.to"); Q_Response::setScriptData('Q.plugins.Streams.invite.url', $invite_url); if (isset($host) && isset($port)) { Q_Response::setScriptData('Q.plugins.Streams.node', array("http://{$host}:{$port}")); } if ($sizes = Q_Config::expect('Streams', 'types', 'Streams/image', 'sizes')) { sort($sizes); Q_Response::setScriptData('Q.plugins.Streams.image.sizes', $sizes); } $defaults = array('readLevel' => Streams::$READ_LEVEL['messages'], 'writeLevel' => Streams::$WRITE_LEVEL['join'], 'adminLevel' => Streams::$ADMIN_LEVEL['invite']); Q_Response::setScriptData('Q.plugins.Streams.defaults', $defaults); if ($froalaKey = Q_Config::get('Streams', 'froala', 'key', null)) { Q_Response::setScriptData('Q.plugins.Streams.froala.key', $froalaKey); } } Q_Response::addStylesheet("plugins/Streams/css/Streams.css"); }
/** * Displays an HTML document that can be printed, ideally with line breaks. * Uses a particular view for the layout. * @param {array} $_REQUEST * @param {string} $_REQUEST.invitingUserId Required. The id of the user that generated the invitations with a call to Streams::invite. * @param {string} $_REQUEST.batch Required. The name of the batch under which invitations were saved during a call to Streams::invite. * @param {string} [$_REQUEST.limit=100] The maximum number of invitations to show on the page * @param {string} [$_REQUEST.offset=0] Used for paging * @param {string} [$_REQUEST.title='Invitations'] Override the title of the document * @param {string} [$_REQUEST.layout='default'] The name of the layout to use for the HTML document * @see Users::addLink() */ function Streams_invitations_response() { Q_Request::requireFields(array('batch', 'invitingUserId'), true); $invitingUserId = $_REQUEST['invitingUserId']; $batch = $_REQUEST['batch']; $user = Users::loggedInUser(true); $stream = Streams::fetchOne(null, $invitingUserId, 'Streams/invitations', true); if (!$stream->testReadLevel('content')) { throw new Users_Exception_NotAuthorized(); } $title = Q::ifset($_REQUEST, 'title', 'Invitations'); $layoutKey = Q::ifset($_REQUEST, 'layout', 'default'); $limit = min(1000, Q::ifset($_REQUEST, 'limit', 100)); $offset = Q::ifset($_REQUEST, 'offset', 0); $layout = Q_Config::expect('Streams', 'invites', 'layout', $layoutKey); $pattern = Streams::invitationsPath($invitingUserId) . DS . $batch . DS . "*.html"; $filenames = glob($pattern); if ($sort = Q_Config::get('Streams', 'invites', 'sort', $batch, null)) { usort($filenames, $sort); } $parts = array(); foreach ($filenames as $f) { if (--$offset >= 0) { continue; } $parts[] = file_get_contents($f); if (--$limit == 0) { break; } } $content = implode("\n\n<div class='Q_pagebreak Streams_invitations_separator'></div>\n\n", $parts); echo Q::view($layout, compact('title', 'content', 'parts')); return false; }
function Overlay_before_Q_responseExtras() { $app = Q_Config::expect('Q', 'app'); Q_Response::addStylesheet('plugins/Q/css/Q.css'); Q_Response::addStylesheet('css/Overlay.css', '@end'); Q_Response::addStylesheet('http://fonts.googleapis.com/css?family=Open+Sans:400italic,400,300,700'); if (Q_Config::get('Q', 'firebug', false)) { Q_Response::addScript("https://getfirebug.com/firebug-lite-debug.js"); } Q_Response::addScript('js/Overlay.js'); Q_Response::setMeta("title", "Customize My Pic!"); Q_Response::setMeta("description", "Make a statement on Facebook by customizing your profile picture, even from your smartphone."); Q_Response::setMeta("image", Q_Html::themedUrl('img/icon/icon.png')); if (Q_Request::isIE()) { header("X-UA-Compatible", "IE=edge"); } header('Vary: User-Agent'); // running an event for loading action-specific extras (if there are any) $uri = Q_Dispatcher::uri(); $module = $uri->module; $action = $uri->action; $event = "{$module}/{$action}/response/responseExtras"; if (Q::canHandle($event)) { Q::event($event); } }
function Users_after_Q_reroute($params, &$stop_dispatch) { $uri = Q_Dispatcher::uri(); $app = Q_Config::expect('Q', 'app'); $ma = $uri->module . '/' . $uri->action; $requireLogin = Q_Config::get('Users', 'requireLogin', array()); if (!isset($requireLogin[$ma])) { return; // We don't have to require login here } $user = Users::loggedInUser(); if ($requireLogin[$ma] === true and !$user) { // require login } else { if ($requireLogin[$ma] === 'facebook' and !Users::facebook($app)) { // require facebook } else { return; // We don't have to require login here } } $redirect_action = Q_Config::get('Users', 'uris', "{$app}/login", "{$app}/welcome"); if ($redirect and $ma != $redirect_action) { Q_Response::redirect($redirect_action); $stop_dispatch = true; return; } }
function Streams_invite_response_data() { if (isset(Streams::$cache['invited'])) { return Streams::$cache['invited']; } $user = Users::loggedInUser(true); $publisherId = Streams::requestedPublisherId(); $streamType = Streams::requestedType(); $invitingUserId = Streams::requestedField('invitingUserId'); $limit = Q::ifset($_REQUEST, 'limit', Q_Config::get('Streams', 'invites', 'limit', 100)); $invited = Streams_Invited::select('*')->where(array('userId' => $user->id, 'state' => 'pending', 'expireTime <' => new Db_Expression('CURRENT_TIMESTAMP')))->limit($limit)->fetchDbRows(null, null, 'token'); $query = Streams_Invite::select('*')->where(array('token' => array_keys($invited))); if (isset($publisherId)) { $query = $query->where(array('publisherId' => $publisherId)); } if (isset($streamType)) { $query = $query->where(array('streamName' => new Db_Range($streamType . '/', true, false, true))); } if (isset($invitingUserId)) { $query = $query->where(array('invitingUserId' => $invitingUserId)); } $invites = $query->fetchDbRows(); $streams = array(); foreach ($invites as $invite) { $stream = new Streams_Stream(); $stream->publisherId = $invite->publisherId; $stream->name = $invite->streamName; if ($stream->retrieve()) { $streams[$invite->token] = $stream->exportArray(); $streams[$invite->token]['displayName'] = $invite->displayName; } } return compact('streams', 'invites'); }
function Streams_after_Q_objects() { $user = Users::loggedInUser(); if (!$user) { return; } $invite = Streams::$followedInvite; if (!$invite) { return; } $displayName = $user->displayName(); if ($displayName) { return; } $stream = new Streams_Stream(); $stream->publisherId = $invite->publisherId; $stream->name = $invite->streamName; if (!$stream->retrieve()) { throw new Q_Exception_MissingRow(array('table' => 'stream', 'criteria' => 'with that name'), 'streamName'); } // Prepare the complete invite dialog $defaults = Q_Config::get("Streams", "types", $stream->type, "invite", "dialog", Q_Config::get("Streams", "defaults", "invite", "dialog", array())); $invitingUser = Users_User::fetch($invite->invitingUserId); list($relations, $related) = Streams::related($user->id, $stream->publisherId, $stream->name, false); $params = array('displayName' => null, 'action' => 'Streams/basic', 'icon' => $user->iconUrl(), 'token' => $invite->token, 'user' => array('icon' => $invitingUser->iconUrl(), 'displayName' => $invitingUser->displayName(array('fullAccess' => true))), 'stream' => $stream->exportArray(), 'relations' => Db::exportArray($relations), 'related' => Db::exportArray($related)); $tree = new Q_Tree($defaults); if ($tree->merge($params)) { $dialogData = $tree->getAll(); if ($dialogData) { Q_Response::setScriptData('Q.plugins.Streams.invite.dialog', $dialogData); Q_Response::addTemplate('Streams/invite/complete'); } } }
function Broadcast_before_Streams_message_Broadcast($params) { extract($params); if (!empty($_REQUEST['link'])) { $parts = parse_url($_REQUEST['link']); if (empty($parts['host'])) { throw new Q_Exception_WrongType(array('field' => 'link', 'type' => 'a valid url'), 'link'); } } $content = array(); foreach (array('link', 'description', 'picture') as $field) { if (!empty($_REQUEST[$field])) { $content[$field] = $_REQUEST[$field]; } } if (!empty($_REQUEST['content'])) { $content['message'] = $_REQUEST['content']; } if (!$content) { throw new Q_Exception_RequiredField(array('field' => 'content'), 'content'); } // Manually adding a link for 'Manage or Remove' $appUrl = Q_Config::get('Users', 'facebookApps', 'Broadcast', 'url', ''); $content['actions'] = Q::json_encode(array(array('name' => 'Manage or Remove', 'link' => $appUrl))); $message->broadcast_instructions = Q::json_encode($content); }
function Users_identifier_post() { $userId = Q::ifset($_REQUEST, 'userId', null); if (isset($userId)) { $user = Users_User::fetch($userId, true); if ($user->emailAddress or $user->mobileNumber) { throw new Q_Exception("This user is already able to log in and set their own email and mobile number."); } } else { $user = Users::loggedInUser(true); } $app = Q_Config::expect('Q', 'app'); $fields = array(); $identifier = Users::requestedIdentifier($type); if (!$type) { throw new Q_Exception("a valid email address or mobile number is required", array('identifier', 'mobileNumber', 'emailAddress')); } if ($type === 'email') { $subject = Q_Config::get('Users', 'transactional', 'identifier', 'subject', "Welcome! Verify your email address."); $view = Q_Config::get('Users', 'transactional', 'identifier', 'body', 'Users/email/addEmail.php'); $user->addEmail($identifier, $subject, $view, array(), array('html' => true)); } else { if ($type === 'mobile') { $view = Q_Config::get('Users', 'transactional', 'identifier', 'sms', 'Users/sms/addMobile.php'); $user->addMobile($identifier, $view); } } }
/** * This tool renders a user avatar * * @param {array} $options An associative array of parameters, containing: * @param {string} [$options.userId] * The user's id. Defaults to id of the logged-in user, if any. * Can be '' for a blank-looking avatar. * @param {boolean} [options.short] * Optional. Renders the short version of the display name. * @param {boolean|integer} [options.icon=false] * Optional. Pass the size in pixels of the (square) icon to render * before the username. Or pass true to render the default size. * @param {array} [options.iconAttributes] * Optional. Array of attributes to render for the icon. * @param {boolean|array} [options.editable=false] * Optional. Whether to provide an interface for editing the user's info. Can be array containing one or more of "icon", "name". * @param {boolean} [$options.show] The parts of the name to show. Can have the letters "f", "l", "u" in any order. * @param {boolean} [options.cacheBust=null] * Number of milliseconds to use for Q_Uri::cacheBust for combating unintended caching on some environments. * @param {boolean} [options.renderOnClient] * If true, only the html container is rendered, so the client will do the rest. */ function Users_avatar_tool($options) { $defaults = array('icon' => false, 'short' => false, 'cacheBust' => null, 'editable' => false); $options = array_merge($defaults, $options); Q_Response::addStylesheet('plugins/Users/css/Users.css'); $loggedInUser = Users::loggedInUser(); $loggedInUserId = $loggedInUser ? $loggedInUser->id : ""; if (empty($options['userId'])) { $options['userId'] = $loggedInUserId; } unset($options['iconAttributes']); if (empty($options['editable'])) { $options['editable'] = array(); } else { if (is_string($options['editable'])) { $options['editable'] = array($options['editable']); } else { if ($options['editable'] === true) { $options['editable'] = array('icon', 'name'); } } } Q_Response::setToolOptions($options); if (!empty($options['renderOnClient'])) { return ''; } $avatar = Streams_Avatar::fetch($loggedInUserId, $options['userId']); if (!$avatar) { return ''; } $result = ''; if ($icon = $options['icon']) { if ($icon === true) { $icon = Q_Config::get('Users', 'icon', 'defaultSize', 40); } $attributes = isset($options['iconAttributes']) ? $options['iconAttributes'] : array(); $class = "Users_avatar_icon Users_avatar_icon_{$icon}"; $attributes['class'] = isset($attributes['class']) ? $attributes['class'] . ' ' . $class : $class; if (isset($options['cacheBust'])) { $attributes['cacheBust'] = $options['cacheBust']; } $result .= Q_Html::img(Users::iconUrl($avatar->icon, "{$icon}.png"), 'user icon', $attributes); } $o = $options['short'] ? array('short' => true) : array(); $o['html'] = true; if (in_array('name', $options['editable'])) { $o['show'] = 'fl'; $streams = Streams::fetch(null, $options['userId'], array('Streams/user/firstName', 'Streams/user/lastName', 'Streams/user/username')); foreach ($streams as $s) { $s->addPreloaded(); } } if (!empty($options['show'])) { $o['show'] = $options['show']; } $displayName = $avatar->displayName($o, 'Someone'); $result .= "<span class='Users_avatar_name'>{$displayName}</span>"; return $result; }
function Users_before_Q_session_save($params) { $row = $params['row']; $row->deviceId = ""; $row->timeout = 0; $row->content = isset($_SESSION) ? Q::json_encode($_SESSION, JSON_FORCE_OBJECT) : "{}"; $row->duration = Q_Config::get('Q', 'session', 'durations', Q_Request::formFactor(), Q_Config::expect('Q', 'session', 'durations', 'session')); }
function Places_before_Q_responseExtras() { Q_Response::addScript('plugins/Places/js/Places.js'); Q_Response::addStylesheet("plugins/Places/css/Places.css"); if ($key = Q_Config::get('Places', 'google', 'keys', 'web', null)) { Q_Response::setScriptData("Q.Places.loadGoogleMaps.key", $key); } }
function Streams_player_Websites_article($options) { $stream = $options['stream']; $emailSubject = Q::ifset($options, 'emailSubject', "Reaching out from your website"); $result = Q::tool('Websites/article', array('publisherId' => $stream->publisherId, 'streamName' => $stream->name, 'html' => array('placeholder' => 'Start editing the article here. Select some text to use the HTML editor.', 'froala' => array('key' => Q_Config::get('Streams', 'froala', 'key', null), 'pasteImage' => true)), 'getintouch' => array('email' => true, 'emailSubject' => $emailSubject, 'sms' => 'Text', 'call' => 'Call', 'class' => 'Q_button clickable'))); $result .= Q::tool("Websites/seo", array('skipIfNotAuthorized' => true, 'publisherId' => $stream->publisherId, 'streamName' => $stream->name)); return $result; }
function Users_user_validate() { if (isset($_REQUEST['userIds']) or isset($_REQUEST['batch'])) { return; } $type = isset($_REQUEST['identifierType']) ? $_REQUEST['identifierType'] : Q_Config::get("Users", "login", "identifierType", "email,mobile"); $parts = explode(',', $type); $accept_mobile = true; $expected = 'email address or mobile number'; $fields = array('emailAddress', 'mobileNumber', 'identifier'); if (count($parts) === 1) { if ($parts[0] === 'email') { $expected = 'email address'; $fields = array('emailAddress', 'identifier'); $accept_mobile = false; } else { if ($parts[0] === 'mobile') { $expected = 'mobile number'; $fields = array('mobileNumber', 'identifier'); } } } if (!isset($_REQUEST['identifier'])) { throw new Q_Exception("a valid {$expected} is required", $fields); } if (!Q_Valid::email($_REQUEST['identifier'])) { if (!$accept_mobile) { throw new Q_Exception("a valid {$expected} is required", $fields); } if (!Q_Valid::phone($_REQUEST['identifier'])) { throw new Q_Exception("a valid {$expected} is required", $fields); } } $identifier = Users::requestedIdentifier($type); // check our db if ($user = Users::userFromContactInfo($type, $identifier)) { $verified = !!Users::identify($type, $identifier); return array('exists' => $user->id, 'verified' => $verified, 'username' => $user->username, 'icon' => $user->icon, 'passphrase_set' => !empty($user->passphraseHash), 'fb_uid' => $user->fb_uid ? $user->fb_uid : null); } if ($type === 'email') { $email = new Users_Email(); Q_Valid::email($identifier, $normalized); $email->address = $normalized; $exists = $email->retrieve(); } else { if ($type === 'mobile') { $mobile = new Users_Mobile(); Q_Valid::phone($identifier, $normalized); $mobile->number = $normalized; $exists = $mobile->retrieve(); } } if (empty($exists) and Q_Config::get('Users', 'login', 'noRegister', false)) { $nicetype = $type === 'email' ? 'email address' : 'mobile number'; throw new Q_Exception("This {$nicetype} was not registered", array('identifier')); } }
/** * 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 Q_response_title() { // The default title $title = Q_Config::get('Q', 'app', basename(APP_DIR)); $action = Q_Dispatcher::uri()->action; if ($action) { $title .= ": {$action}"; } return $title; }
/** * We are going to implement a subset of the OAuth 1.0a functionality for now, * and later we can expand it to match the full OAuth specification. */ function Users_authorize_response() { if (Q_Response::getErrors()) { Q_Dispatcher::showErrors(); } $response_type = 'token'; $token_type = 'bearer'; $client_id = $_REQUEST['client_id']; $state = $_REQUEST['state']; $skip = Q::ifset($_REQUEST, 'skip', false); $scope = Users_OAuth::requestedScope(true, $scopes); $client = Users_User::fetch($client_id, true); if (!$client) { throw new Q_Exception_MissingRow(array('table' => 'client user', 'criteria' => "id = '{$client_id}'"), 'client_id'); } if (empty($client->url)) { throw new Q_Exception("Client app needs to register url", 'client_id'); } $redirect_uri = Q::ifset($_REQUEST, 'redirect_uri', $client->url); $user = Users::loggedInUser(); $oa = null; if (isset(Users::$cache['oAuth'])) { $oa = Users::$cache['oAuth']; } else { if ($user) { $oa = new Users_OAuth(); $oa->client_id = $client_id; $oa->userId = $user->id; $oa->state = $state; $oa = $oa->retrieve(); } } $remaining = $scope; if ($oa and $oa->wasRetrieved()) { // User is logged in and already has a token for this client_id and state $paths = Q_Config::get('Users', 'authorize', 'clients', Q::app(), 'redirectPaths', false); $path = substr($redirect_uri, strlen($client->url) + 1); $p = array('response_type' => $response_type, 'token_type' => $token_type, 'access_token' => $oa->access_token, 'expires_in' => $oa->token_expires_seconds, 'scope' => implode(' ', $scope), 'state' => $oa->state); $p = Q_Utils::sign($p, 'Q.Users.oAuth'); // the redirect uri could be a native app url scheme $s = strpos($redirect_uri, '#') === false ? '#' : '&'; $redirect_uri = Q_Uri::from($redirect_uri . $s . http_build_query($p), false)->toUrl(); if (!Q::startsWith($redirect_uri, $client->url) or is_array($paths) and !in_array($path, $paths)) { throw new Users_Exception_Redirect(array('uri' => $redirect_uri)); } Q_Response::redirect($redirect_uri); return false; } $terms_label = Users::termsLabel('authorize'); Q_Response::setScriptData('Q.Users.authorize', compact('client_id', 'redirect_uri', 'scope', 'scopes', 'remaining', 'state', 'response_type', 'skip')); $content = Q::view('Users/content/authorize.php', compact('client', 'user', 'redirect_uri', 'scope', 'scopes', 'remaining', 'state', 'terms_label', 'response_type', 'skip')); Q_Response::setSlot('content', $content); Q_Response::setSlot('column0', $content); return true; }
function Websites_0_8_Users_mysql() { $userId = Q_Config::get("Websites", "user", "id", null); if (!$userId) { throw new Q_Exception('Websites: Please fill in the config field "Websites"/"user"/"id"'); } Users_Label::addLabel('Websites/admins', $userId, 'Website Admins', 'labels/Websites/admins', false); if (!file_exists('Websites')) { Q_Utils::symlink(WEBSITES_PLUGIN_FILES_DIR . DS . 'Websites' . DS . 'icons' . DS . 'labels' . DS . 'Websites', USERS_PLUGIN_FILES_DIR . DS . 'Users' . DS . 'icons' . DS . 'Websites'); } }
function Users_user_response_data($params) { $identifier = Users::requestedIdentifier($type); // check our db if ($user = Users::userFromContactInfo($type, $identifier)) { $verified = !!Users::identify($type, $identifier); return array('exists' => $user->id, 'verified' => $verified, 'username' => $user->username, 'icon' => $user->icon, 'passphrase_set' => !empty($user->passphraseHash), 'fb_uid' => $user->fb_uid ? $user->fb_uid : null); } if ($type === 'email') { $email = new Users_Email(); Q_Valid::email($identifier, $normalized); $email->address = $normalized; $exists = $email->retrieve(); } else { if ($type === 'mobile') { $mobile = new Users_Mobile(); Q_Valid::phone($identifier, $normalized); $mobile->number = $normalized; $exists = $mobile->retrieve(); } } if (empty($exists) and Q_Config::get('Users', 'login', 'noRegister', false)) { $nicetype = $type === 'email' ? 'email address' : 'mobile number'; throw new Q_Exception("This {$nicetype} was not registered", array('identifier')); } // Get Gravatar info // WARNING: INTERNET_REQUEST $hash = md5(strtolower(trim($identifier))); $thumbnailUrl = Q_Request::baseUrl() . "/action.php/Users/thumbnail?hash={$hash}&size=80&type=" . Q_Config::get('Users', 'login', 'iconType', 'wavatar'); $json = @file_get_contents("http://www.gravatar.com/{$hash}.json"); $result = json_decode($json, true); if ($result) { if ($type === 'email') { $result['emailExists'] = !empty($exists); } else { if ($type === 'mobile') { $result['mobileExists'] = !empty($exists); } } return $result; } // otherwise, return default $email_parts = explode('@', $identifier, 2); $result = array("entry" => array(array("id" => "571", "hash" => "357a20e8c56e69d6f9734d23ef9517e8", "requestHash" => "357a20e8c56e69d6f9734d23ef9517e8", "profileUrl" => "http://gravatar.com/test", "preferredUsername" => ucfirst($email_parts[0]), "thumbnailUrl" => $thumbnailUrl, "photos" => array(), "displayName" => "", "urls" => array()))); if ($type === 'email') { $result['emailExists'] = !empty($exists); } else { $result['mobileExists'] = !empty($exists); } if ($terms_label = Users::termsLabel('register')) { $result['termsLabel'] = $terms_label; } return $result; }
function Platform_before_Users_computePassphraseHash($params) { $user = $params['user']; $passphrase = $params['passphrase']; $isHashed = $params['isHashed']; $appRootUrl = Q_Config::get("Platform", "appRootUrl", Q_Config::expect("Q", "web", "appRootUrl")); if (!$isHashed) { $passphrase = sha1($passphrase . "\t" . $appRootUrl . "\t" . $this->id); } return Users::hashPassphrase($passphrase, $user->passphraseHash); }
function Broadcast_widget_response_widget() { if (!empty($_REQUEST['css'])) { Q_Response::addStylesheet($_REQUEST['css']); } $explanation = Q::ifset($_REQUEST, 'explanation', Q_Config::get('Broadcast', 'text', 'explanation', '')); $button = Q::ifset($_REQUEST, 'button', Q_Config::get('Broadcast', 'text', 'button', '')); $checkbox = Q::ifset($_REQUEST, 'checkbox', Q_Config::get('Broadcast', 'text', 'checkbox', '')); Q_Response::addScript('plugins/Broadcast/js/Broadcast.js'); return Q::view('Broadcast/widget/widget.php', compact('explanation', 'button', 'checkbox')); }
function Places_before_Q_responseExtras() { Q_Response::addScript('plugins/Places/js/Places.js'); Q_Response::addStylesheet("plugins/Places/css/Places.css"); if ($key = Q_Config::get('Places', 'google', 'keys', 'web', null)) { Q_Response::setScriptData("Q.plugins.Places.loadGoogleMaps.key", $key); } $miles = Q_Config::expect('Places', 'nearby', 'miles'); Q_Response::setScriptData("Q.plugins.Places.nearby.miles", $miles); $defaultMiles = Q_Config::expect('Places', 'nearby', 'defaultMiles'); Q_Response::setScriptData("Q.plugins.Places.nearby.defaultMiles", $defaultMiles); }
/** * userChooser tool * @param array $options * "maxResults" => the maximum number of results to show, defaults to 3 * "onSuccess" => the name of the function for what to do * "placeholder" => override the default placeholder text, * "exclude" => associative array of userId => true, where userId are the ids of the users * to exclude from the results. Defaults to id of logged-in user, if logged in. */ function Streams_userChooser_tool($options) { $maxResults = Q_Config::get('Streams', 'userChooser', 'maxResults', 3); $placeholder = "Start typing..."; extract($options); if (!isset($exclude) and $user = Users::loggedInUser()) { $exclude = array($user->id => true); } Q_Response::addScript('plugins/Streams/js/Streams.js'); Q_Response::setToolOptions(compact('onSuccess', 'maxResults', 'exclude')); return Q_Html::input('query', '', array('class' => 'text', 'placeholder' => $placeholder, 'autocomplete' => 'off')); }
/** * Lets the user search for streams they can relate a given stream to, and relate it * @class Streams relate * @constructor * @param {array} [$options] Override various options for this tool * @param {string} $publisherId publisher id of the stream to relate * @param {string} $streamName name of stream to relate * @param {string} [$communityId=Users::communityId()] id of the user publishing the streams to relate to * @param {array} [$types=Q_Config::expect('Streams','relate','types')] the types of streams the user can select * @param {array} [$typeNames] pairs of array($type => $typeName) to override names of the types, which would otherwise be taken from the types * @param {Boolean} [options.multiple=true] whether the user can select multiple types for the lookup * @param {boolean} [$relateFrom=false] if true, will relate FROM the user-selected stream TO the streamName instead * @param {string} [$types=Q_Config::expect('Streams','relate','types')] the types of streams the user can select * @param {Q.Event} [$options.onRelate] This event handler occurs when a stream is successfully related */ function Streams_relate_tool($options) { Q_Valid::requireFields(array('publisherId', 'streamName'), $options, true); if (!isset($options['communityId'])) { $options['communityId'] = Users::communityId(); } if (!isset($options['types'])) { $options['types'] = Q_Config::get('Streams', 'relate', 'types', array()); } Q_Response::setToolOptions($options); return ''; }
function Streams_message_tool($options) { extract($options); $user = Users::loggedInUser(); if (!$user) { throw new Users_Exception_NotLoggedIn(); } if (empty($publisherId)) { $publisherId = Streams::requestedPublisherId(); } if (empty($publisherId)) { $publisherId = $_REQUEST['publisherId'] = $user->id; } if (empty($name)) { $name = Streams::requestedName(true); } $stream = Streams::fetch($user->id, $publisherId, $name); $stream = !empty($stream) ? reset($stream) : null; if (!$stream) { throw new Q_Exception_MissingRow(array('table' => 'stream', 'criteria' => 'with that name'), 'streamName'); } if (!$stream->testReadLevel('messages') || !$stream->testWriteLevel('post')) { throw new Users_Exception_NotAuthorized(); } $hidden = array('publisherId' => $publisherId, 'streamName' => $name); $fields = array('stream' => array('label' => 'Stream', 'type' => 'static', 'value' => $stream->title)); $type = Streams::requestedType(); // check if stream has messages $types = Q_Config::get('Streams', 'messages', $stream->type, array()); if (count($types) === 0) { throw new Q_Exception("Stream of type '{$stream->type}' does not support messages"); } if (!empty($type) && !in_array($type, $types)) { throw new Q_Exception("Requested message type '{$type}' is not alowed for streams of type '{$stream->type}'"); } if (!empty($type)) { $hidden['type'] = $type; $fields['type'] = array('label' => 'Message type', 'type' => 'static', 'value' => $type); } else { $fields['type'] = array('label' => 'Message type', 'type' => 'select', 'options' => array_merge(array('' => 'Select type'), array_combine($types, $types)), 'value' => ''); } $fields['content'] = array('label' => 'Content', 'type' => 'textarea'); $fields['submit'] = array('label' => '', 'type' => 'submit_buttons', 'options' => array('submit' => 'Post')); return Q_Html::tag('h3', array(), 'Post a message') . Q_Html::form(Q_Request::baseUrl() . '/action.php/Streams/message', 'post', array(), Q_Html::hidden($hidden) . Q::tool('Q/form', array('fields' => $fields, 'onSuccess' => 'function (data) { if (data.errors) alert(data.errors); else { alert("Message posted"); var message = Q.getObject(["slots", "form", "fields"], data); Q.handle(Q.info.baseUrl+"/plugins/Streams/message?publisherId="+message.publisherId+"&name="+message.streamName); } }'))); }