function subscribeProfile($user, $author, $activity) { $profile = $user->getProfile(); if ($activity->objects[0]->id == $author->id) { if (!$this->trusted) { // TRANS: Client exception thrown when trying to force a subscription for an untrusted user. throw new ClientException(_('Cannot force subscription for untrusted user.')); } $other = $activity->actor; $otherUser = User::getKV('uri', $other->id); if (!$otherUser instanceof User) { // TRANS: Client exception thrown when trying to force a remote user to subscribe. throw new Exception(_('Cannot force remote user to subscribe.')); } $otherProfile = $otherUser->getProfile(); // XXX: don't do this for untrusted input! Subscription::ensureStart($otherProfile, $profile); } else { if (empty($activity->actor) || $activity->actor->id == $author->id) { $other = $activity->objects[0]; try { $otherProfile = Profile::fromUri($other->id); // TRANS: Client exception thrown when trying to subscribe to an unknown profile. } catch (UnknownUriException $e) { // Let's convert it to a client exception instead of server. throw new ClientException(_('Unknown profile.')); } Subscription::ensureStart($profile, $otherProfile); } else { // TRANS: Client exception thrown when trying to import an event not related to the importing user. throw new Exception(_('This activity seems unrelated to our user.')); } } }
function moveActivity($act, $sink, $user, $remote) { if (empty($user)) { // TRANS: Exception thrown if a non-existing user is provided. %s is a user ID. throw new Exception(sprintf(_('No such user "%s".'), $act->actor->id)); } switch ($act->verb) { /* case ActivityVerb::FAVORITE: $this->log(LOG_INFO, "Moving favorite of {$act->objects[0]->id} by ". "{$act->actor->id} to {$remote->nickname}."); // push it, then delete local $sink->postActivity($act); $notice = Notice::getKV('uri', $act->objects[0]->id); if (!empty($notice)) { $fave = Fave::pkeyGet(array('user_id' => $user->id, 'notice_id' => $notice->id)); $fave->delete(); } break;*/ case ActivityVerb::POST: $this->log(LOG_INFO, "Moving notice {$act->objects[0]->id} by " . "{$act->actor->id} to {$remote->nickname}."); // XXX: send a reshare, not a post $sink->postActivity($act); $notice = Notice::getKV('uri', $act->objects[0]->id); if (!empty($notice)) { $notice->delete(); } break; case ActivityVerb::JOIN: $this->log(LOG_INFO, "Moving group join of {$act->objects[0]->id} by " . "{$act->actor->id} to {$remote->nickname}."); $sink->postActivity($act); $group = User_group::getKV('uri', $act->objects[0]->id); if (!empty($group)) { $user->leaveGroup($group); } break; case ActivityVerb::FOLLOW: if ($act->actor->id === $user->getUri()) { $this->log(LOG_INFO, "Moving subscription to {$act->objects[0]->id} by " . "{$act->actor->id} to {$remote->nickname}."); $sink->postActivity($act); try { $other = Profile::fromUri($act->objects[0]->id); Subscription::cancel($user->getProfile(), $other); } catch (UnknownUriException $e) { // Can't cancel subscription if we don't know who to alert } } else { $otherUser = User::getKV('uri', $act->actor->id); if (!empty($otherUser)) { $this->log(LOG_INFO, "Changing sub to {$act->objects[0]->id}" . "by {$act->actor->id} to {$remote->nickname}."); $otherProfile = $otherUser->getProfile(); Subscription::ensureStart($otherProfile, $remote); Subscription::cancel($otherProfile, $user->getProfile()); } else { $this->log(LOG_NOTICE, "Not changing sub to {$act->objects[0]->id}" . "by remote {$act->actor->id} " . "to {$remote->nickname}."); } } break; } }
/** * Register a new user account and profile and set up default subscriptions. * If a new-user welcome message is configured, this will be sent. * * @param array $fields associative array of optional properties * string 'bio' * string 'email' * bool 'email_confirmed' pass true to mark email as pre-confirmed * string 'fullname' * string 'homepage' * string 'location' informal string description of geolocation * float 'lat' decimal latitude for geolocation * float 'lon' decimal longitude for geolocation * int 'location_id' geoname identifier * int 'location_ns' geoname namespace to interpret location_id * string 'nickname' REQUIRED * string 'password' (may be missing for eg OpenID registrations) * string 'code' invite code * ?string 'uri' permalink to notice; defaults to local notice URL * @return User object * @throws Exception on failure */ static function register(array $fields) { // MAGICALLY put fields into current scope extract($fields); $profile = new Profile(); if (!empty($email)) { $email = common_canonical_email($email); } // Normalize _and_ check whether it is in use. Throw NicknameException on failure. $profile->nickname = Nickname::normalize($nickname, true); $profile->profileurl = common_profile_url($profile->nickname); if (!empty($fullname)) { $profile->fullname = $fullname; } if (!empty($homepage)) { $profile->homepage = $homepage; } if (!empty($bio)) { $profile->bio = $bio; } if (!empty($location)) { $profile->location = $location; $loc = Location::fromName($location); if (!empty($loc)) { $profile->lat = $loc->lat; $profile->lon = $loc->lon; $profile->location_id = $loc->location_id; $profile->location_ns = $loc->location_ns; } } $profile->created = common_sql_now(); $user = new User(); $user->nickname = $profile->nickname; $invite = null; // Users who respond to invite email have proven their ownership of that address if (!empty($code)) { $invite = Invitation::getKV($code); if ($invite instanceof Invitation && $invite->address && $invite->address_type == 'email' && $invite->address == $email) { $user->email = $invite->address; } } if (isset($email_confirmed) && $email_confirmed) { $user->email = $email; } // Set default-on options here, otherwise they'll be disabled // initially for sites using caching, since the initial encache // doesn't know about the defaults in the database. $user->emailnotifysub = 1; $user->emailnotifynudge = 1; $user->emailnotifymsg = 1; $user->emailnotifyattn = 1; $user->emailmicroid = 1; $user->emailpost = 1; $user->jabbermicroid = 1; $user->created = common_sql_now(); if (Event::handle('StartUserRegister', array($profile))) { $profile->query('BEGIN'); $id = $profile->insert(); if ($id === false) { common_log_db_error($profile, 'INSERT', __FILE__); $profile->query('ROLLBACK'); // TRANS: Profile data could not be inserted for some reason. throw new ServerException(_m('Could not insert profile data for new user.')); } $user->id = $id; if (!empty($uri)) { $user->uri = $uri; } else { $user->uri = common_user_uri($user); } if (!empty($password)) { // may not have a password for OpenID users $user->password = common_munge_password($password, $id); } $result = $user->insert(); if ($result === false) { common_log_db_error($user, 'INSERT', __FILE__); $profile->query('ROLLBACK'); // TRANS: User data could not be inserted for some reason. throw new ServerException(_m('Could not insert user data for new user.')); } // Everyone is subscribed to themself $subscription = new Subscription(); $subscription->subscriber = $user->id; $subscription->subscribed = $user->id; $subscription->created = $user->created; $result = $subscription->insert(); if (!$result) { common_log_db_error($subscription, 'INSERT', __FILE__); $profile->query('ROLLBACK'); // TRANS: Subscription data could not be inserted for some reason. throw new ServerException(_m('Could not insert subscription data for new user.')); } // Mark that this invite was converted if (!empty($invite)) { $invite->convert($user); } if (!empty($email) && !$user->email) { $confirm = new Confirm_address(); $confirm->code = common_confirmation_code(128); $confirm->user_id = $user->id; $confirm->address = $email; $confirm->address_type = 'email'; $result = $confirm->insert(); if (!$result) { common_log_db_error($confirm, 'INSERT', __FILE__); $profile->query('ROLLBACK'); // TRANS: Email confirmation data could not be inserted for some reason. throw new ServerException(_m('Could not insert email confirmation data for new user.')); } } if (!empty($code) && $user->email) { $user->emailChanged(); } // Default system subscription $defnick = common_config('newuser', 'default'); if (!empty($defnick)) { $defuser = User::getKV('nickname', $defnick); if (empty($defuser)) { common_log(LOG_WARNING, sprintf("Default user %s does not exist.", $defnick), __FILE__); } else { Subscription::ensureStart($profile, $defuser->getProfile()); } } $profile->query('COMMIT'); if (!empty($email) && !$user->email) { mail_confirm_address($user, $confirm->code, $profile->nickname, $email); } // Welcome message $welcome = common_config('newuser', 'welcome'); if (!empty($welcome)) { $welcomeuser = User::getKV('nickname', $welcome); if (empty($welcomeuser)) { common_log(LOG_WARNING, sprintf("Welcome user %s does not exist.", $defnick), __FILE__); } else { $notice = Notice::saveNew($welcomeuser->id, sprintf(_('Welcome to %1$s, @%2$s!'), common_config('site', 'name'), $user->nickname), 'system'); } } Event::handle('EndUserRegister', array($profile)); } if (!$user instanceof User) { throw new ServerException('User could not be registered. Probably an event hook that failed.'); } return $user; }
/** * Handle request * * Does the subscription and returns results. * * @param Array $args unused. * * @return void */ function handle($args) { // Throws exception on error $sub = Subscription::ensureStart($this->user->getProfile(), $this->other); if ($this->boolean('ajax')) { $this->startHTML('text/xml;charset=utf-8'); $this->elementStart('head'); // TRANS: Page title when subscription succeeded. $this->element('title', null, _('Subscribed')); $this->elementEnd('head'); $this->elementStart('body'); if ($sub instanceof Subscription) { $form = new UnsubscribeForm($this, $this->other); } else { $form = new CancelSubscriptionForm($this, $this->other); } $form->show(); $this->elementEnd('body'); $this->endHTML(); } else { $url = common_local_url('subscriptions', array('nickname' => $this->user->nickname)); common_redirect($url, 303); } }
function sendInvitations() { if (Event::handle('StartSendInvitations', array(&$this))) { // CSRF protection $token = $this->trimmed('token'); if (!$token || $token != common_session_token()) { // TRANS: Client error displayed when the session token does not match or is not given. $this->showForm(_('There was a problem with your session token. Try again, please.')); return; } $user = common_current_user(); $profile = $user->getProfile(); $bestname = $profile->getBestName(); $sitename = common_config('site', 'name'); $personal = $this->trimmed('personal'); $addresses = explode("\n", $this->trimmed('addresses')); foreach ($addresses as $email) { $email = trim($email); $valid = null; try { if (Event::handle('StartValidateUserEmail', array(null, $email, &$valid))) { $valid = Validate::email($email, common_config('email', 'check_domain')); Event::handle('EndValidateUserEmail', array(null, $email, &$valid)); } if ($valid) { if (Event::handle('StartValidateEmailInvite', array($user, $email, &$valid))) { $valid = true; Event::handle('EndValidateEmailInvite', array($user, $email, &$valid)); } } if (!$valid) { // TRANS: Form validation message when providing an e-mail address that does not validate. // TRANS: %s is an invalid e-mail address. $this->showForm(sprintf(_('Invalid email address: %s.'), $email)); return; } } catch (ClientException $e) { $this->showForm($e->getMessage()); return; } } $this->already = array(); $this->subbed = array(); foreach ($addresses as $email) { $email = common_canonical_email($email); try { // If this user is already registered, subscribe to it! $other = Profile::getByEmail($email); if ($user->isSubscribed($other)) { $this->already[] = $other; } else { try { Subscription::ensureStart($profile, $other); $this->subbed[] = $other; } catch (Exception $e) { // subscription failed, but keep working common_debug('Invitation-based subscription failed: ' . $e->getMessage()); } } } catch (NoSuchUserException $e) { // If email was not known, let's send an invite! $this->sent[] = $email; $this->sendInvitation($email, $user, $personal); } } $this->mode = 'sent'; $this->showPage(); Event::handle('EndSendInvitations', array($this)); } }