Esempio n. 1
0
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);
        }
    }
}
Esempio n. 2
0
function Streams_stream_response_content()
{
    $publisherId = Streams::requestedPublisherId(true);
    $name = Streams::requestedName(true);
    $fields = Streams::requestedFields();
    $user = Users::loggedInUser();
    $userId = $user ? $user->id : 0;
    $stream = isset(Streams::$cache['stream']) ? Streams::$cache['stream'] : null;
    if (!isset($stream)) {
        throw new Q_Exception_MissingRow(array('table' => 'stream', 'criteria' => 'that name'));
    }
    if ($publisherId != $userId and !$stream->testReadLevel('content')) {
        Q_Response::setNotice('Streams/stream/response/content', 'This content is hidden from you.', true);
        return '';
    }
    // show stream as usual
    return Q::view('Streams/content/stream.php', compact('publisherId', 'name', 'fields', 'user', 'stream'));
}
Esempio n. 3
0
function Users_activate_post()
{
    Q_Valid::nonce(true);
    $email = $mobile = $type = $user = null;
    extract(Users::$cache, EXTR_IF_EXISTS);
    if (isset($_REQUEST['passphrase'])) {
        if (empty($_REQUEST['passphrase'])) {
            throw new Q_Exception("You can't set a blank passphrase.", 'passphrase');
        }
        $isHashed = !empty($_REQUEST['isHashed']);
        if ($isHashed and $isHashed !== 'true' and intval($_REQUEST['isHashed']) > 1) {
            // this will let us introduce other values for isHashed in the future
            throw new Q_Exception("Please set isHashed to 0 or 1", 'isHashed');
        }
        // Save the pass phrase even if there may be a problem adding an email later.
        // At least the user will be able to log in.
        $user->passphraseHash = $user->computePassphraseHash($_REQUEST['passphrase'], $isHashed);
        Q_Response::setNotice("Users/activate/passphrase", "Your pass phrase has been saved.", true);
        // Log the user in, since they were able to set the passphrase
        Users::setLoggedInUser($user);
        // This also saves the user.
        if (empty($user->passphraseHash)) {
            throw new Q_Exception("Please set a pass phrase on your account", 'passphrase', true);
        }
    }
    if ($type) {
        if ($type == 'email address') {
            $user->setEmailAddress($email->address);
            // may throw exception
        } else {
            if ($type == 'mobile number') {
                $user->setMobileNumber($mobile->number);
                // may throw exception
            }
        }
        // Log the user in, since they have just added an email to their account
        Users::setLoggedInUser($user);
        // This also saves the user.
        Q_Response::removeNotice('Users/activate/objects');
        Q_Response::setNotice("Users/activate/activated", "Your {$type} has been activated.", true);
    }
    Users::$cache['passphrase_set'] = true;
    Users::$cache['success'] = true;
}
function Users_after_Users_addIdentifier($params)
{
    extract($params);
    if (!Q_Config::get('Users', 'notices', 'identifier', true)) {
        return;
    }
    $loggedInUser = Users::loggedInUser();
    if (!$loggedInUser or $loggedInUser->id !== $user->id) {
        return;
    }
    if (isset($email)) {
        $resend_button = "<button id='notices_set_email' class='Q_button'>Need it re-sent?</button>";
        Q_Response::setNotice('Users/email', "Please check your email for an activation link. {$resend_button}");
    } else {
        if (isset($mobile)) {
            $resend_button = "<button id='notices_set_mobile' class='Q_button'>Need it re-sent?</button>";
            Q_Response::setNotice('Users/mobile', "Please check your mobile phone for an activation message. {$resend_button}");
        }
    }
}
Esempio n. 5
0
 /**
  * Send e-mail message
  * @method sendMessage
  * @param {string} $subject
  *  The subject. May contain variable references to members
  *  of the $fields array.
  * @param {string} $view
  *  The name of a view for the body. Fields are passed to it.
  * @param {array} $fields=array()
  *  The fields referenced in the subject and/or view
  * @param {array} $options=array()
  *  Array of options. Can include:<br/>
  *  "html" => Defaults to false. Whether to send as HTML email.<br/>
  *  "name" => A human-readable name in addition to the address.<br/>
  *  "from" => An array of (emailAddress, human_readable_name)<br/>
  *  "delay" => A delay, in milliseconds, to wait until sending email. Only works if Node server is listening.
  */
 function sendMessage($subject, $view, $fields = array(), $options = array())
 {
     /**
      * @event Users/email/sendMessage {before}
      * @param {string} subject
      * @param {string} view
      * @param {array} fields
      * @param {array} options
      * @return {boolean}
      */
     $result = Q::event('Users/email/sendMessage', compact('subject', 'view', 'fields', 'options'), 'before');
     if (isset($result)) {
         return $result;
     }
     if (!Q_Valid::email($this->address, $emailAddress)) {
         throw new Q_Exception_WrongType(array('field' => '$this->address', 'type' => 'email address', 'emailAddress' => $this->address));
     }
     $app = Q_Config::expect('Q', 'app');
     $subject = Q_Handlebars::renderSource($subject, $fields);
     $body = Q::view($view, $fields);
     if (!Q_Config::get('Users', 'email', 'smtp', 'sendmail')) {
         Q_Response::setNotice("Q/email", "Please set up SMTP in Users/email/smtp as in docs.", false);
         return true;
     }
     $overrideLog = Q::event('Users/email/log', compact('emailAddress', 'subject', 'body'), 'before');
     if (!isset($overrideLog) and $key = Q_Config::get('Users', 'email', 'log', 'key', null)) {
         Q::log("\nSent email message to {$emailAddress}:\n{$subject}\n{$body}", $key);
     }
     $from = Q::ifset($options, 'from', Q_Config::get('Users', 'email', 'from', null));
     if (!isset($from)) {
         // deduce from base url
         $url_parts = parse_url(Q_Request::baseUrl());
         $domain = $url_parts['host'];
         $from = array("email@{$domain}", $domain);
     }
     if (!is_array($from)) {
         throw new Q_Exception_WrongType(array('field' => '$options["from"]', 'type' => 'array'));
     }
     $sent = false;
     if (!empty($options['delay'])) {
         // Try to use Node.js to send the message
         $sent = Q_Utils::sendToNode(array("Q/method" => "Users/sendMessage", "delay" => $options['delay'], "emailAddress" => $emailAddress, "subject" => $subject, "body" => $body, "options" => $options));
     }
     if (!$sent) {
         // Set up the default mail transport
         $smtp = Q_Config::get('Users', 'email', 'smtp', array('host' => 'sendmail'));
         $host = Q::ifset($smtp, 'host', 'sendmail');
         if ($host === 'sendmail') {
             $transport = new Zend_Mail_Transport_Sendmail('-f' . reset($from));
         } else {
             if (is_array($smtp)) {
                 $host = $smtp['host'];
                 unset($smtp['host']);
             } else {
                 if (is_string($smtp)) {
                     $host = $smtp;
                     $smtp = null;
                 }
             }
             $transport = new Zend_Mail_Transport_Smtp($host, $smtp);
         }
         $mail = new Zend_Mail();
         $mail->setFrom(reset($from), next($from));
         if (isset($options['name'])) {
             $mail->addTo($emailAddress, $options['name']);
         } else {
             $mail->addTo($emailAddress);
         }
         $mail->setSubject($subject);
         if (empty($options['html'])) {
             $mail->setBodyText($body);
         } else {
             $mail->setBodyHtml($body);
         }
         try {
             $mail->send($transport);
         } catch (Exception $e) {
             throw new Users_Exception_EmailMessage(array('error' => $e->getMessage()));
         }
     }
     /**
      * @event Users/email/sendMessage {after}
      * @param {string} subject
      * @param {string} view
      * @param {array} fields
      * @param {array} options
      * @param {string} mail
      */
     Q::event('Users/email/sendMessage', compact('subject', 'view', 'fields', 'options', 'mail', 'app'), 'after');
     return true;
 }
Esempio n. 6
0
function Users_activate_objects_mobile($mobileNumber, &$mobile)
{
    Q_Response::removeNotice('Users/activate/objects');
    $mobile = new Users_Mobile();
    if (!Q_Valid::phone($mobileNumber, $normalized)) {
        return;
    }
    $mobile->number = $normalized;
    if (!$mobile->retrieve()) {
        throw new Q_Exception_MissingRow(array('table' => 'mobile phone', 'criteria' => "number {$normalized}"));
    }
    $user = Users::loggedInUser();
    if ($user) {
        if ($user->id != $mobile->userId) {
            throw new Q_Exception("You are logged in as a different user. Please log out and click the link again.");
        }
    } else {
        $user = new Users_User();
        $user->id = $mobile->userId;
        if (!$user->retrieve()) {
            throw new Q_Exception_MissingRow(array('table' => 'user', 'criteria' => 'id = ' . $user->id));
        }
    }
    if ($mobile->activationCode != $_REQUEST['code']) {
        throw new Q_Exception("The activation code does not match. Did you get a newer message?", 'code');
    }
    $timestamp = Users_Mobile::db()->getCurrentTimestamp();
    if ($timestamp > Users_Mobile::db()->fromDateTime($mobile->activationCodeExpires)) {
        throw new Q_Exception("Activation code expired");
    }
    if (Q_Request::method() !== 'POST' and empty($_REQUEST['p']) and isset($user->mobileNumber) and $user->mobileNumber == $mobile->number) {
        Q_Response::setNotice('Users/activate/objects', "{$normalized} has already been activated for {$user->username}", true);
        return $user;
    }
    return $user;
}
Esempio n. 7
0
function Streams_before_Q_objects()
{
    $token = Q_Request::special('Streams.token', null);
    if ($token === null) {
        return;
    }
    $invite = Streams_Invite::fromToken($token);
    if (!$invite) {
        throw new Q_Exception_MissingRow(array('table' => 'invite', 'criteria' => "token = '{$token}"), 'token');
    }
    // did invite expire?
    $ts = Streams_Invite::db()->select("CURRENT_TIMESTAMP")->fetchAll(PDO::FETCH_NUM);
    if (isset($invite->expireTime) and $invite->expireTime < $ts[0][0]) {
        $invite->state = 'expired';
        $invite->save();
    }
    // is invite still pending?
    if ($invite->state !== 'pending') {
        switch ($invite->state) {
            case 'expired':
                $exception = new Streams_Exception_AlreadyExpired(null, 'token');
                break;
            case 'accepted':
                $exception = new Streams_Exception_AlreadyAccepted(null, 'token');
                break;
            case 'declined':
                $exception = new Streams_Exception_AlreadyDeclined(null, 'token');
                break;
            case 'forwarded':
                $exception = new Streams_Exception_AlreadyForwarded(null, 'token');
                break;
            default:
                $exception = new Q_Exception("This invite has already been " . $invite->state, 'token');
                break;
        }
        $shouldThrow = Q::event('Streams/objects/inviteException', compact('invite', 'exception'), 'before');
        if ($shouldThrow === null) {
            Q_Response::setNotice('Streams/objects', $exception->getMessage(), true);
        } else {
            if ($shouldThrow === true) {
                throw $exception;
            }
        }
    }
    // now process the invite
    $invitedUser = Users_User::fetch($invite->userId, true);
    $stream = Streams::fetchOne($invitedUser->id, $invite->publisherId, $invite->streamName);
    if (!$stream) {
        throw new Q_Exception_MissingRow(array('table' => 'stream', 'criteria' => "publisherId = '{$invite->publisherId}', name = '{$invite->streamName}'"));
    }
    $byUser = Users_User::fetch($invite->invitingUserId, true);
    $byStream = Streams::fetchOne($byUser->id, $invite->publisherId, $invite->streamName);
    if (!$byStream) {
        throw new Q_Exception_MissingRow(array('table' => 'stream', 'criteria' => "publisherId = '{$invite->publisherId}', name = '{$invite->streamName}'"));
    }
    $access = new Streams_Access();
    $access->publisherId = $byStream->publisherId;
    $access->streamName = $byStream->name;
    $access->ofUserId = $invite->userId;
    $specified_access = false;
    foreach (array('readLevel', 'writeLevel', 'adminLevel') as $level_type) {
        $access->{$level_type} = -1;
        if (empty($invite->{$level_type})) {
            continue;
        }
        // Give access level from the invite.
        // However, if inviting user has a lower access level now,
        // then give that level instead, unless it is lower than
        // what the invited user would have had otherwise.
        $min = min($invite->{$level_type}, $byStream->get($level_type, 0));
        if ($min > $stream->get($level_type, 0)) {
            $access->{$level_type} = $min;
            $specified_access = true;
        }
    }
    if ($specified_access) {
        $access->save(true);
    }
    // now log invited user in
    $user = Users::loggedInUser();
    if (empty($user) or $user->id !== $invite->userId) {
        $user = new Users_User();
        $user->id = $invite->userId;
        if (!$user->retrieve()) {
            // The user who was invited doesn't exist
            // This shouldn't happen. We just silently log it and return.
            Q::log("Sanity check failed: invite with {$invite->token} pointed to nonexistent user");
            return;
        }
        Users::setLoggedInUser($user);
    }
    // accept invite and autosubscribe if first time
    if ($invite->accept() and !$stream->subscription($user->id)) {
        $stream->subscribe();
    }
    // retain the invite object for further processing
    Streams::$followedInvite = $invite;
}
Esempio n. 8
0
 /**
  * @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(null, null, array('lock' => 'FOR UPDATE'))) {
                     self::$session_db_row = $row;
                 } else {
                     // Start a new session with our own 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), 'before')) {
                         $row->save();
                         self::id($row->{$id_field});
                         // this sets the session cookie as well
                         self::$session_db_row = $row;
                     }
                 }
             } else {
                 self::id($id);
             }
         }
         if (!empty($_SERVER['HTTP_HOST'])) {
             session_start();
         } else {
             if (empty($_SESSION)) {
                 $_SESSION = array();
             }
         }
     } 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);
         }
     }
     /**
      * @event Q/session/start {after}
      */
     Q::event('Q/session/start', array(), 'after');
     return true;
 }
Esempio n. 9
0
 /**
  * @method sendMessage
  * @param {string} $view
  *  The name of a view for the message. Fields are passed to this array.
  * @param {array} $fields=array()
  *  The fields referenced in the subject and/or view
  * @param {array} $options=array()
  *  Array of options. Can include:<br/>
  *  "delay" => A delay, in milliseconds, to wait until sending email. Only works if Node server is listening.
  * @return {boolean}
  * @throws {Q_Exception_WrongType}
  *	If phone number is invalid
  */
 function sendMessage($view, $fields = array(), $options = array())
 {
     /**
      * @event Users/sms/sendMessage {before}
      * @param {string} view
      * @param {array} fields
      * @param {array} options
      * @return {boolean}
      */
     $result = Q::event('Users/sms/sendMessage', compact('view', 'fields', 'options'), 'before');
     if (isset($result)) {
         return $result;
     }
     if (!Q_Valid::phone($this->number, $number)) {
         throw new Q_Exception_WrongType(array('field' => '$this->number', 'type' => 'mobile number', 'mobileNumber' => $this->number));
     }
     $app = Q_Config::expect('Q', 'app');
     $body = Q::view($view, $fields);
     $overrideLog = Q::event('Users/mobile/log', compact('mobileNumber', 'body'), 'before');
     if (is_null($overrideLog) and $key = Q_Config::get('Users', 'mobile', 'log', 'key', null)) {
         Q::log("\nSent mobile message to {$this->number}:\n{$body}", $key);
     }
     $sent = false;
     if (!empty($options['delay'])) {
         // Try to use Node.js to send the message
         $sent = Q_Utils::sendToNode(array("Q/method" => "Users/sendMessage", "delay" => $options['delay'], "mobileNumber" => $number, "body" => $body, "options" => $options));
     }
     if (!$sent) {
         $from = Q::ifset($options, 'from', Q_Config::get('Users', 'mobile', 'from', null));
         if (!isset($from)) {
             // deduce from base url
             $url_parts = parse_url(Q_Request::baseUrl());
             $domain = $url_parts['host'];
             $from = array("notifications@{$domain}", $domain);
         }
         $sid = Q_Config::get('Users', 'mobile', 'twilio', 'sid', null);
         $token = Q_Config::get('Users', 'mobile', 'twilio', 'token', null);
         if ($sid and $token) {
             $client = new Services_Twilio($sid, $token);
             $message = $client->account->sms_messages->create($from, $number, Q::view($view, $fields));
         } else {
             if (!Q_Config::get('Users', 'email', 'smtp', null)) {
                 Q_Response::setNotice("Q/mobile", "Please set up transport in Users/mobile/twilio as in docs", false);
                 return true;
             }
             if (!is_array($from)) {
                 $from = array($from, "{$app} activation");
             }
             // Set up the default mail transport
             $host = Q_Config::get('Users', 'email', 'smtp', 'host', 'sendmail');
             if ($host === 'sendmail') {
                 $transport = new Zend_Mail_Transport_Sendmail('-f' . reset($from));
             } else {
                 if (is_array($host)) {
                     $smtp = $host;
                     $host = $smtp['host'];
                     unset($smtp['host']);
                 } else {
                     $smtp = null;
                 }
                 $transport = new Zend_Mail_Transport_Smtp($host, $smtp);
             }
             $mail = new Zend_Mail();
             $from_name = reset($from);
             $mail->setFrom(next($from), $from_name);
             $gateways = Q_Config::get('Users', 'mobile', 'gateways', array('at&t' => 'txt.att.net', 'sprint' => 'messaging.sprintpcs.com', 'verizon' => 'vtext.com', 't-mobile' => 'tmomail.net'));
             $number2 = substr($this->number, 2);
             foreach ($gateways as $k => $v) {
                 $mail->addTo($number2 . '@' . $v);
             }
             $mail->setBodyText($body);
             try {
                 $mail->send($transport);
             } catch (Exception $e) {
                 throw new Users_Exception_MobileMessage(array('error' => $e->getMessage()));
             }
         }
     }
     /**
      * @event Users/sms/sendMessage {after}
      * @param {string} view
      * @param {array} fields
      * @param {array} options
      * @param {string} mail
      */
     Q::event('Users/email/sendMessage', compact('view', 'fields', 'options', 'mail', 'app'), 'after');
     return true;
 }