/** * Prepare to run */ function prepare($args) { parent::prepare($args); if (!common_logged_in()) { // TRANS: Client error displayed when trying to perform an action while not logged in. $this->clientError(_('You must be logged in to unsubscribe from a list.')); } // Only allow POST requests if ($_SERVER['REQUEST_METHOD'] != 'POST') { // TRANS: Client error displayed when trying to use another method than POST. $this->clientError(_('This action only accepts POST requests.')); } // 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->clientError(_('There was a problem with your session token.' . ' Try again, please.')); } $tagger_arg = $this->trimmed('tagger'); $tag_arg = $this->trimmed('tag'); $id = intval($this->arg('id')); if ($id) { $this->peopletag = Profile_list::getKV('id', $id); } else { // TRANS: Client error displayed when trying to perform an action without providing an ID. $this->clientError(_('No ID given.'), 404); } if (!$this->peopletag || $this->peopletag->private) { // TRANS: Client error displayed trying to reference a non-existing list. $this->clientError(_('No such list.'), 404); } $this->tagger = Profile::getKV('id', $this->peopletag->tagger); return true; }
/** * Check pre-requisites and instantiate attributes * * @param Array $args array of arguments (URL, GET, POST) * * @return boolean success flag */ function prepare($args) { parent::prepare($args); // 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->clientError(_('There was a problem with your session token.' . ' Try again, please.')); return false; } // Only for logged-in users $this->user = common_current_user(); if (empty($this->user)) { // TRANS: Error message displayed when trying to perform an action that requires a logged in user. $this->clientError(_('Not logged in.')); return false; } $id = $this->arg('peopletag_id'); $this->peopletag = Profile_list::staticGet('id', $id); if (empty($this->peopletag)) { // TRANS: Client error displayed trying to reference a non-existing list. $this->clientError(_('No such list.')); return false; } $field = $this->arg('field'); if (!in_array($field, array('fulltext', 'nickname', 'fullname', 'description', 'location', 'uri'))) { // TRANS: Client error displayed when trying to add an unindentified field to profile. // TRANS: %s is a field name. $this->clientError(sprintf(_('Unidentified field %s.'), htmlspecialchars($field)), 404); return false; } $this->field = $field; return true; }
static function add($peopletag, $profile) { if ($peopletag->private) { return false; } if (Event::handle('StartSubscribePeopletag', array($peopletag, $profile))) { $args = array('profile_tag_id' => $peopletag->id, 'profile_id' => $profile->id); $existing = Profile_tag_subscription::pkeyGet($args); if (!empty($existing)) { return $existing; } $sub = new Profile_tag_subscription(); $sub->profile_tag_id = $peopletag->id; $sub->profile_id = $profile->id; $sub->created = common_sql_now(); $result = $sub->insert(); if (!$result) { common_log_db_error($sub, 'INSERT', __FILE__); // TRANS: Exception thrown when inserting a list subscription in the database fails. throw new Exception(_('Adding list subscription failed.')); } $ptag = Profile_list::getKV('id', $peopletag->id); $ptag->subscriberCount(true); Event::handle('EndSubscribePeopletag', array($peopletag, $profile)); return $ptag; } }
/** * Show the menu * * @return void */ function show() { $user = null; // FIXME: we should probably pass this in $action = $this->action->trimmed('action'); $nickname = $this->action->trimmed('tagger'); $tag = $this->action->trimmed('tag'); if ($nickname) { $user = User::staticGet('nickname', $nickname); $user_profile = $user->getProfile(); if ($tag) { $tag = Profile_list::pkeyGet(array('tagger' => $user->id, 'tag' => $tag)); } else { $tag = false; } } else { $user_profile = false; } $this->out->elementStart('ul', array('class' => 'nav')); if (Event::handle('StartPeopletagGroupNav', array($this))) { // People tag timeline $this->out->menuItem(common_local_url('showprofiletag', array('tagger' => $user_profile->nickname, 'tag' => $tag->tag)), _m('MENU', 'List'), sprintf(_('%1$s list by %2$s.'), $tag->tag, $user_profile && $user_profile->fullname ? $user_profile->fullname : $nickname), $action == 'showprofiletag', 'nav_timeline_peopletag'); // Tagged $this->out->menuItem(common_local_url('peopletagged', array('tagger' => $user->nickname, 'tag' => $tag->tag)), _m('MENU', 'Listed'), sprintf(_('%1$s list by %2$s.'), $tag->tag, $user_profile && $user_profile->fullname ? $user_profile->fullname : $nickname), $action == 'peopletagged', 'nav_peopletag_tagged'); // Subscribers $this->out->menuItem(common_local_url('peopletagsubscribers', array('tagger' => $user->nickname, 'tag' => $tag->tag)), _m('MENU', 'Subscribers'), sprintf(_('Subscribers to %1$s list by %2$s.'), $tag->tag, $user_profile && $user_profile->fullname ? $user_profile->fullname : $nickname), $action == 'peopletagsubscribers', 'nav_peopletag_subscribers'); $cur = common_current_user(); if (!empty($cur) && $user_profile->id == $cur->id) { // Edit $this->out->menuItem(common_local_url('editpeopletag', array('tagger' => $user->nickname, 'tag' => $tag->tag)), _m('MENU', 'Edit'), sprintf(_('Edit %s list by you.'), $tag->tag, $user_profile && $user_profile->fullname ? $user_profile->fullname : $nickname), $action == 'editpeopletag', 'nav_peopletag_edit'); } Event::handle('EndPeopletagGroupNav', array($this)); } $this->out->elementEnd('ul'); }
protected function doStreamPreparation() { $tag = common_canonical_tag($this->arg('tag')); try { $this->peopletag = Profile_list::getByPK(array('tagger' => $this->target->getID(), 'tag' => $tag)); } catch (NoResultException $e) { // TRANS: Client error displayed trying to reference a non-existing list. throw new ClientException('No such list.'); } if ($this->peopletag->private && !$this->peopletag->getTagger()->sameAs($this->scoped)) { // TRANS: Client error displayed trying to reference a non-existing list. throw new AuthorizationException('You do not have permission to see this list.'); } }
function prepare($args) { parent::prepare($args); if (common_config('singleuser', 'enabled')) { $tagger_arg = User::singleUserNickname(); } else { $tagger_arg = $this->arg('tagger'); } $tag_arg = $this->arg('tag'); $tagger = common_canonical_nickname($tagger_arg); $tag = common_canonical_tag($tag_arg); // Permanent redirect on non-canonical nickname if ($tagger_arg != $tagger || $tag_arg != $tag) { $args = array('tagger' => $nickname, 'tag' => $tag); if ($this->page != 1) { $args['page'] = $this->page; } common_redirect(common_local_url('showprofiletag', $args), 301); return false; } if (!$tagger) { // TRANS: Client error displayed when a tagger is expected but not provided. $this->clientError(_('No tagger.'), 404); return false; } $user = User::staticGet('nickname', $tagger); if (!$user) { // TRANS: Client error displayed trying to perform an action related to a non-existing user. $this->clientError(_('No such user.'), 404); return false; } $this->tagger = $user->getProfile(); $this->peopletag = Profile_list::pkeyGet(array('tagger' => $user->id, 'tag' => $tag)); $current = common_current_user(); $can_see = !empty($this->peopletag) && (!$this->peopletag->private || $this->peopletag->private && $this->peopletag->tagger === $current->id); if (!$can_see) { // TRANS: Client error displayed trying to reference a non-existing list. $this->clientError(_('No such list.'), 404); return false; } $this->page = $this->arg('page') ? $this->arg('page') + 0 : 1; $this->userProfile = Profile::current(); $stream = new PeopletagNoticeStream($this->peopletag, $this->userProfile); $this->notice = $stream->getNotices(($this->page - 1) * NOTICES_PER_PAGE, NOTICES_PER_PAGE + 1); if ($this->page > 1 && $this->notice->N == 0) { // TRANS: Server error when page not found (404). $this->serverError(_('No such page.'), $code = 404); } return true; }
function prepare($args) { parent::prepare($args); $id = $this->trimmed('id'); if (!$id) { // TRANS: Client error displayed trying to perform an action without providing an ID. $this->clientError(_m('No ID.')); } $this->peopletag = Profile_list::staticGet('id', $id); if (empty($this->peopletag)) { // TRANS: Client error displayed when referring to a non-existing list. $this->clientError(_m('No such list.')); } $oprofile = Ostatus_profile::staticGet('peopletag_id', $id); if (!empty($oprofile)) { // TRANS: Client error displayed when trying to send a message to a remote list. $this->clientError(_m('Cannot accept remote posts for a remote list.')); } return true; }
function prepare($args) { parent::prepare($args); $this->page = $this->arg('page') ? $this->arg('page') + 0 : 1; if (common_config('singleuser', 'enabled')) { $tagger_arg = User::singleUserNickname(); } else { $tagger_arg = $this->arg('tagger'); } $tag_arg = $this->arg('tag'); $tagger = common_canonical_nickname($tagger_arg); $tag = common_canonical_tag($tag_arg); // Permanent redirect on non-canonical nickname if ($tagger_arg != $tagger || $tag_arg != $tag) { $args = array('tagger' => $nickname, 'tag' => $tag); if ($this->page != 1) { $args['page'] = $this->page; } common_redirect(common_local_url('peopletagged', $args), 301); return false; } if (!$tagger) { // TRANS: Client error displayed when a tagger is expected but not provided. $this->clientError(_('No tagger.'), 404); return false; } $user = User::staticGet('nickname', $tagger); if (!$user) { // TRANS: Client error displayed trying to perform an action related to a non-existing user. $this->clientError(_('No such user.'), 404); return false; } $this->tagger = $user->getProfile(); $this->peopletag = Profile_list::pkeyGet(array('tagger' => $user->id, 'tag' => $tag)); if (!$this->peopletag) { // TRANS: Client error displayed trying to reference a non-existing list. $this->clientError(_('No such list.'), 404); return false; } return true; }
protected function prepare(array $args = array()) { parent::prepare($args); $id = $this->trimmed('id'); if (!$id) { // TRANS: Client error displayed trying to perform an action without providing an ID. $this->clientError(_m('No ID.')); } $this->peopletag = Profile_list::getKV('id', $id); if (!$this->peopletag instanceof Profile_list) { // TRANS: Client error displayed when referring to a non-existing list. $this->clientError(_m('No such list.')); } $this->target = $this->peopletag; $remote_list = Ostatus_profile::getKV('peopletag_id', $id); if ($remote_list instanceof Ostatus_profile) { // TRANS: Client error displayed when trying to send a message to a remote list. $this->clientError(_m('Cannot accept remote posts for a remote list.')); } return true; }
function prepare($args) { parent::prepare($args); $id = $this->arg('id'); $tagger_id = $this->arg('tagger_id'); if (!$id) { // TRANS: Client error displayed trying to perform an action without providing an ID. $this->clientError(_('No ID.')); } common_debug("Peopletag id {$id} by user id {$tagger_id}"); $this->peopletag = Profile_list::getKV('id', $id); if (!$this->peopletag) { // TRANS: Client error displayed trying to reference a non-existing list. $this->clientError(_('No such list.'), 404); } $user = User::getKV('id', $tagger_id); if (!$user) { // remote peopletag, permanently redirect common_redirect($this->peopletag->permalink(), 301); } return true; }
/** * Find @-mentions in the given text, using the given notice object as context. * References will be resolved with common_relative_profile() against the user * who posted the notice. * * Note the return data format is internal, to be used for building links and * such. Should not be used directly; rather, call common_linkify_mentions(). * * @param string $text * @param Notice $notice notice in whose context we're building links * * @return array * * @access private */ function common_find_mentions($text, Notice $notice) { // The getProfile call throws NoProfileException on failure $sender = $notice->getProfile(); $mentions = array(); if (Event::handle('StartFindMentions', array($sender, $text, &$mentions))) { // Get the context of the original notice, if any $origAuthor = null; $origNotice = null; $origMentions = array(); // Is it a reply? if ($notice instanceof Notice) { try { $origNotice = $notice->getParent(); $origAuthor = $origNotice->getProfile(); $ids = $origNotice->getReplies(); foreach ($ids as $id) { $repliedTo = Profile::getKV('id', $id); if ($repliedTo instanceof Profile) { $origMentions[$repliedTo->nickname] = $repliedTo; } } } catch (NoProfileException $e) { common_log(LOG_WARNING, sprintf('Notice %d author profile id %d does not exist', $origNotice->id, $origNotice->profile_id)); } catch (NoParentNoticeException $e) { // This notice is not in reply to anything } catch (Exception $e) { common_log(LOG_WARNING, __METHOD__ . ' got exception ' . get_class($e) . ' : ' . $e->getMessage()); } } $matches = common_find_mentions_raw($text); foreach ($matches as $match) { try { $nickname = Nickname::normalize($match[0]); } catch (NicknameException $e) { // Bogus match? Drop it. continue; } // Try to get a profile for this nickname. // Start with conversation context, then go to // sender context. if ($origAuthor instanceof Profile && $origAuthor->nickname == $nickname) { $mentioned = $origAuthor; } else { if (!empty($origMentions) && array_key_exists($nickname, $origMentions)) { $mentioned = $origMentions[$nickname]; } else { $mentioned = common_relative_profile($sender, $nickname); } } if ($mentioned instanceof Profile) { $user = User::getKV('id', $mentioned->id); if ($user instanceof User) { $url = common_local_url('userbyid', array('id' => $user->id)); } else { $url = $mentioned->profileurl; } $mention = array('mentioned' => array($mentioned), 'type' => 'mention', 'text' => $match[0], 'position' => $match[1], 'url' => $url); if (!empty($mentioned->fullname)) { $mention['title'] = $mentioned->fullname; } $mentions[] = $mention; } } // @#tag => mention of all subscriptions tagged 'tag' preg_match_all('/(?:^|[\\s\\.\\,\\:\\;]+)@#([\\pL\\pN_\\-\\.]{1,64})/', $text, $hmatches, PREG_OFFSET_CAPTURE); foreach ($hmatches[1] as $hmatch) { $tag = common_canonical_tag($hmatch[0]); $plist = Profile_list::getByTaggerAndTag($sender->id, $tag); if (!$plist instanceof Profile_list || $plist->private) { continue; } $tagged = $sender->getTaggedSubscribers($tag); $url = common_local_url('showprofiletag', array('tagger' => $sender->nickname, 'tag' => $tag)); $mentions[] = array('mentioned' => $tagged, 'type' => 'list', 'text' => $hmatch[0], 'position' => $hmatch[1], 'url' => $url); } preg_match_all('/(?:^|[\\s\\.\\,\\:\\;]+)!(' . Nickname::DISPLAY_FMT . ')/', $text, $hmatches, PREG_OFFSET_CAPTURE); foreach ($hmatches[1] as $hmatch) { $nickname = Nickname::normalize($hmatch[0]); $group = User_group::getForNickname($nickname, $sender); if (!$group instanceof User_group || !$sender->isMember($group)) { continue; } $profile = $group->getProfile(); $mentions[] = array('mentioned' => array($profile), 'type' => 'group', 'text' => $hmatch[0], 'position' => $hmatch[1], 'url' => $group->permalink(), 'title' => $group->getFancyName()); } Event::handle('EndFindMentions', array($sender, $text, &$mentions)); } return $mentions; }
/** * Create local ostatus_profile and profile/user_group entries for * the provided remote user or group. * This should never return null -- you will either get an object or * an exception will be thrown. * * @param ActivityObject $object * @param array $hints * * @return Ostatus_profile */ protected static function createActivityObjectProfile($object, $hints = array()) { $homeuri = $object->id; $discover = false; if (!$homeuri) { common_log(LOG_DEBUG, __METHOD__ . " empty actor profile URI: " . var_export($activity, true)); // TRANS: Exception. throw new Exception(_m('No profile URI.')); } $user = User::staticGet('uri', $homeuri); if ($user) { // TRANS: Exception. throw new Exception(_m('Local user cannot be referenced as remote.')); } if (OStatusPlugin::localGroupFromUrl($homeuri)) { // TRANS: Exception. throw new Exception(_m('Local group cannot be referenced as remote.')); } $ptag = Profile_list::staticGet('uri', $homeuri); if ($ptag) { $local_user = User::staticGet('id', $ptag->tagger); if (!empty($local_user)) { // TRANS: Exception. throw new Exception(_m('Local list cannot be referenced as remote.')); } } if (array_key_exists('feedurl', $hints)) { $feeduri = $hints['feedurl']; } else { $discover = new FeedDiscovery(); $feeduri = $discover->discoverFromURL($homeuri); } if (array_key_exists('salmon', $hints)) { $salmonuri = $hints['salmon']; } else { if (!$discover) { $discover = new FeedDiscovery(); $discover->discoverFromFeedURL($hints['feedurl']); } $salmonuri = $discover->getAtomLink(Salmon::NS_REPLIES); } if (array_key_exists('hub', $hints)) { $huburi = $hints['hub']; } else { if (!$discover) { $discover = new FeedDiscovery(); $discover->discoverFromFeedURL($hints['feedurl']); } $huburi = $discover->getHubLink(); } if (!$huburi && !common_config('feedsub', 'fallback_hub')) { // We can only deal with folks with a PuSH hub throw new FeedSubNoHubException(); } $oprofile = new Ostatus_profile(); $oprofile->uri = $homeuri; $oprofile->feeduri = $feeduri; $oprofile->salmonuri = $salmonuri; $oprofile->created = common_sql_now(); $oprofile->modified = common_sql_now(); if ($object->type == ActivityObject::PERSON) { $profile = new Profile(); $profile->created = common_sql_now(); self::updateProfile($profile, $object, $hints); $oprofile->profile_id = $profile->insert(); if (!$oprofile->profile_id) { // TRANS: Server exception. throw new ServerException(_m('Cannot save local profile.')); } } else { if ($object->type == ActivityObject::GROUP) { $group = new User_group(); $group->uri = $homeuri; $group->created = common_sql_now(); self::updateGroup($group, $object, $hints); $oprofile->group_id = $group->insert(); if (!$oprofile->group_id) { // TRANS: Server exception. throw new ServerException(_m('Cannot save local profile.')); } } else { if ($object->type == ActivityObject::_LIST) { $ptag = new Profile_list(); $ptag->uri = $homeuri; $ptag->created = common_sql_now(); self::updatePeopletag($ptag, $object, $hints); $oprofile->peopletag_id = $ptag->insert(); if (!$oprofile->peopletag_id) { // TRANS: Server exception. throw new ServerException(_m('Cannot save local list.')); } } } } $ok = $oprofile->insert(); if (!$ok) { // TRANS: Server exception. throw new ServerException(_m('Cannot save OStatus profile.')); } $avatar = self::getActivityObjectAvatar($object, $hints); if ($avatar) { try { $oprofile->updateAvatar($avatar); } catch (Exception $ex) { // Profile is saved, but Avatar is messed up. We're // just going to continue. common_log(LOG_WARNING, "Exception saving OStatus profile avatar: " . $ex->getMessage()); } } return $oprofile; }
function tagExists($tag) { $args = array('tagger' => $this->tagger->id, 'tag' => $tag); $ptag = Profile_list::pkeyGet($args); return !empty($ptag); }
function getTagSubscriptions($offset = 0, $limit = null, $since_id = 0, $max_id = 0) { $lists = new Profile_list(); $subs = new Profile_tag_subscription(); $lists->joinAdd(array('id', 'profile_tag_subscription:profile_tag_id')); #@fixme: postgres (round(date_part('epoch', my_date))) $lists->selectAdd('unix_timestamp(profile_tag_subscription.created) as "cursor"'); $lists->whereAdd('profile_tag_subscription.profile_id = ' . $this->id); if ($since_id > 0) { $lists->whereAdd('cursor > ' . $since_id); } if ($max_id > 0) { $lists->whereAdd('cursor <= ' . $max_id); } if ($offset >= 0 && !is_null($limit)) { $lists->limit($offset, $limit); } $lists->orderBy('"cursor" DESC'); $lists->find(); return $lists; }
function getLists() { $fn = array($this->target, 'getTagSubscriptions'); # 20 lists list($this->lists, $this->next_cursor, $this->prev_cursor) = Profile_list::getAtCursor($fn, array(), $this->cursor, 20); }
static function unTag($tagger, $tagged, $tag) { $ptag = Profile_tag::pkeyGet(array('tagger' => $tagger, 'tagged' => $tagged, 'tag' => $tag)); if (!$ptag) { return true; } if (Event::handle('StartUntagProfile', array($ptag))) { $orig = clone $ptag; $result = $ptag->delete(); if (!$result) { common_log_db_error($this, 'DELETE', __FILE__); return false; } Event::handle('EndUntagProfile', array($orig)); if ($result) { $profile_list = Profile_list::pkeyGet(array('tag' => $tag, 'tagger' => $tagger)); if (!empty($profile_list)) { $profile_list->taggedCount(true); } self::blowCaches($tagger, $tagged); return true; } return false; } }
/** * Build the canonical profile URI+URL of the requested user or group */ function targetProfile() { if ($this->nickname) { $user = User::staticGet('nickname', $this->nickname); if ($user) { return common_local_url('userbyid', array('id' => $user->id)); } else { // TRANS: Client error. $this->clientError(_m('No such user.')); } } else { if ($this->group) { $group = Local_group::staticGet('nickname', $this->group); if ($group) { return common_local_url('groupbyid', array('id' => $group->group_id)); } else { // TRANS: Client error. $this->clientError(_m('No such group.')); } } else { if ($this->peopletag && $this->tagger) { $user = User::staticGet('nickname', $this->tagger); if (empty($user)) { // TRANS: Client error. $this->clientError(_m('No such user.')); } $peopletag = Profile_list::getByTaggerAndTag($user->id, $this->peopletag); if ($peopletag) { return common_local_url('profiletagbyid', array('tagger_id' => $user->id, 'id' => $peopletag->id)); } // TRANS: Client error. $this->clientError(_m('No such list.')); } else { // TRANS: Client error. $this->clientError(_m('No local user or group nickname provided.')); } } } }
function initProfileLists() { printfnq("Ensuring all profile tags have a corresponding list..."); $ptag = new Profile_tag(); $ptag->selectAdd(); $ptag->selectAdd('tagger, tag, count(*) as tagged_count'); $ptag->whereAdd('NOT EXISTS (SELECT tagger, tagged from profile_list ' . 'where profile_tag.tagger = profile_list.tagger ' . 'and profile_tag.tag = profile_list.tag)'); $ptag->groupBy('tagger, tag'); $ptag->orderBy('tagger, tag'); if ($ptag->find()) { while ($ptag->fetch()) { $plist = new Profile_list(); $plist->tagger = $ptag->tagger; $plist->tag = $ptag->tag; $plist->private = 0; $plist->created = common_sql_now(); $plist->modified = $plist->created; $plist->mainpage = common_local_url('showprofiletag', array('tagger' => $plist->getTagger()->nickname, 'tag' => $plist->tag)); $plist->tagged_count = $ptag->tagged_count; $plist->subscriber_count = 0; $plist->insert(); $orig = clone $plist; // After insert since it uses auto-generated ID $plist->uri = common_local_url('profiletagbyid', array('id' => $plist->id, 'tagger_id' => $plist->tagger)); $plist->update($orig); } } printfnq("DONE.\n"); }
/** * Find @-mentions in the given text, using the given notice object as context. * References will be resolved with common_relative_profile() against the user * who posted the notice. * * Note the return data format is internal, to be used for building links and * such. Should not be used directly; rather, call common_linkify_mentions(). * * @param string $text * @param Profile $sender the Profile that is sending the current text * @param Notice $parent the Notice this text is in reply to, if any * * @return array * * @access private */ function common_find_mentions($text, Profile $sender, Notice $parent = null) { $mentions = array(); if (Event::handle('StartFindMentions', array($sender, $text, &$mentions))) { // Get the context of the original notice, if any $origMentions = array(); // Does it have a parent notice for context? if ($parent instanceof Notice) { $ids = $parent->getReplies(); // replied-to _profile ids_ foreach ($ids as $id) { try { $repliedTo = Profile::getByID($id); $origMentions[$repliedTo->getNickname()] = $repliedTo; } catch (NoResultException $e) { // continue foreach } } } $matches = common_find_mentions_raw($text); foreach ($matches as $match) { try { $nickname = Nickname::normalize($match[0]); } catch (NicknameException $e) { // Bogus match? Drop it. continue; } // Try to get a profile for this nickname. // Start with conversation context, then go to // sender context. if ($parent instanceof Notice && $parent->getProfile()->getNickname() === $nickname) { $mentioned = $parent->getProfile(); } else { if (!empty($origMentions) && array_key_exists($nickname, $origMentions)) { $mentioned = $origMentions[$nickname]; } else { // sets to null if no match $mentioned = common_relative_profile($sender, $nickname); } } if ($mentioned instanceof Profile) { $user = User::getKV('id', $mentioned->id); try { $url = $mentioned->getUrl(); } catch (InvalidUrlException $e) { $url = common_local_url('userbyid', array('id' => $mentioned->getID())); } $mention = array('mentioned' => array($mentioned), 'type' => 'mention', 'text' => $match[0], 'position' => $match[1], 'length' => mb_strlen($match[0]), 'title' => $mentioned->getFullname(), 'url' => $url); $mentions[] = $mention; } } // @#tag => mention of all subscriptions tagged 'tag' preg_match_all('/(?:^|[\\s\\.\\,\\:\\;]+)@#([\\pL\\pN_\\-\\.]{1,64})/', $text, $hmatches, PREG_OFFSET_CAPTURE); foreach ($hmatches[1] as $hmatch) { $tag = common_canonical_tag($hmatch[0]); $plist = Profile_list::getByTaggerAndTag($sender->getID(), $tag); if (!$plist instanceof Profile_list || $plist->private) { continue; } $tagged = $sender->getTaggedSubscribers($tag); $url = common_local_url('showprofiletag', array('nickname' => $sender->getNickname(), 'tag' => $tag)); $mentions[] = array('mentioned' => $tagged, 'type' => 'list', 'text' => $hmatch[0], 'position' => $hmatch[1], 'length' => mb_strlen($hmatch[0]), 'url' => $url); } preg_match_all('/(?:^|[\\s\\.\\,\\:\\;]+)!(' . Nickname::DISPLAY_FMT . ')/', $text, $hmatches, PREG_OFFSET_CAPTURE); foreach ($hmatches[1] as $hmatch) { $nickname = Nickname::normalize($hmatch[0]); $group = User_group::getForNickname($nickname, $sender); if (!$group instanceof User_group || !$sender->isMember($group)) { continue; } $profile = $group->getProfile(); $mentions[] = array('mentioned' => array($profile), 'type' => 'group', 'text' => $hmatch[0], 'position' => $hmatch[1], 'length' => mb_strlen($hmatch[0]), 'url' => $group->permalink(), 'title' => $group->getFancyName()); } Event::handle('EndFindMentions', array($sender, $text, &$mentions)); } return $mentions; }
/** * Check pre-requisites and instantiate attributes * * @param Array $args array of arguments (URL, GET, POST) * * @return boolean success flag */ function prepare($args) { parent::prepare($args); // 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->clientError(_('There was a problem with your session token.' . ' Try again, please.')); return false; } // Only for logged-in users $this->user = common_current_user(); if (empty($this->user)) { // TRANS: Error message displayed when trying to perform an action that requires a logged in user. $this->clientError(_('Not logged in.')); return false; } // Profile to subscribe to $tagged_id = $this->arg('tagged'); $this->tagged = Profile::staticGet('id', $tagged_id); if (empty($this->tagged)) { // TRANS: Client error displayed trying to perform an action related to a non-existing profile. $this->clientError(_('No such profile.')); return false; } $id = $this->arg('peopletag_id'); $this->peopletag = Profile_list::staticGet('id', $id); if (empty($this->peopletag)) { // TRANS: Client error displayed trying to reference a non-existing list. $this->clientError(_('No such list.')); return false; } // OMB 0.1 doesn't have a mechanism for local-server- // originated tag. $omb01 = Remote_profile::staticGet('id', $tagged_id); if (!empty($omb01)) { // TRANS: Client error displayed when trying to add an OMB 0.1 remote profile to a list. $this->clientError(_('You cannot list an OMB 0.1 ' . 'remote profile with this action.')); return false; } return true; }
/** * Get notices * * @return array notices */ function getNotices() { $fn = array($this->list, 'getNotices'); list($this->notices, $this->next_cursor, $this->prev_cursor) = Profile_list::getAtCursor($fn, array(), $this->cursor, 20); if (!$this->notices) { $this->notices = array(); } }
function showContent() { $offset = ($this->page - 1) * PEOPLETAGS_PER_PAGE; $limit = PEOPLETAGS_PER_PAGE + 1; $ptags = new Profile_list(); $ptags->tag = $this->tag; $user = common_current_user(); if (empty($user)) { $ckey = sprintf('profile_list:tag:%s', $this->tag); $ptags->private = false; $ptags->orderBy('profile_list.modified DESC'); $c = Cache::instance(); if ($offset + $limit <= PEOPLETAG_CACHE_WINDOW && !empty($c)) { $cached_ptags = Profile_list::getCached($ckey, $offset, $limit); if ($cached_ptags === false) { $ptags->limit(0, PEOPLETAG_CACHE_WINDOW); $ptags->find(); Profile_list::setCache($ckey, $ptags, $offset, $limit); } else { $ptags = clone $cached_ptags; } } else { $ptags->limit($offset, $limit); $ptags->find(); } } else { $ptags->whereAdd('(profile_list.private = false OR (' . ' profile_list.tagger =' . $user->id . ' AND profile_list.private = true) )'); $ptags->orderBy('profile_list.modified DESC'); $ptags->find(); } $pl = new PeopletagList($ptags, $this); $cnt = $pl->show(); $this->pagination($this->page > 1, $cnt > PEOPLETAGS_PER_PAGE, $this->page, 'peopletag', array('tag' => $this->tag)); }
/** * Find @-mentions in the given text, using the given notice object as context. * References will be resolved with common_relative_profile() against the user * who posted the notice. * * Note the return data format is internal, to be used for building links and * such. Should not be used directly; rather, call common_linkify_mentions(). * * @param string $text * @param Notice $notice notice in whose context we're building links * * @return array * * @access private */ function common_find_mentions($text, $notice) { $mentions = array(); $sender = Profile::staticGet('id', $notice->profile_id); if (empty($sender)) { return $mentions; } if (Event::handle('StartFindMentions', array($sender, $text, &$mentions))) { // Get the context of the original notice, if any $originalAuthor = null; $originalNotice = null; $originalMentions = array(); // Is it a reply? if (!empty($notice) && !empty($notice->reply_to)) { $originalNotice = Notice::staticGet('id', $notice->reply_to); if (!empty($originalNotice)) { $originalAuthor = Profile::staticGet('id', $originalNotice->profile_id); $ids = $originalNotice->getReplies(); foreach ($ids as $id) { $repliedTo = Profile::staticGet('id', $id); if (!empty($repliedTo)) { $originalMentions[$repliedTo->nickname] = $repliedTo; } } } } $matches = common_find_mentions_raw($text); foreach ($matches as $match) { try { $nickname = Nickname::normalize($match[0]); } catch (NicknameException $e) { // Bogus match? Drop it. continue; } // Try to get a profile for this nickname. // Start with conversation context, then go to // sender context. if (!empty($originalAuthor) && $originalAuthor->nickname == $nickname) { $mentioned = $originalAuthor; } else { if (!empty($originalMentions) && array_key_exists($nickname, $originalMentions)) { $mentioned = $originalMentions[$nickname]; } else { $mentioned = common_relative_profile($sender, $nickname); } } if (!empty($mentioned)) { $user = User::staticGet('id', $mentioned->id); if ($user) { $url = common_local_url('userbyid', array('id' => $user->id)); } else { $url = $mentioned->profileurl; } $mention = array('mentioned' => array($mentioned), 'text' => $match[0], 'position' => $match[1], 'url' => $url); if (!empty($mentioned->fullname)) { $mention['title'] = $mentioned->fullname; } $mentions[] = $mention; } } // @#tag => mention of all subscriptions tagged 'tag' preg_match_all('/(?:^|[\\s\\.\\,\\:\\;]+)@#([\\pL\\pN_\\-\\.]{1,64})/', $text, $hmatches, PREG_OFFSET_CAPTURE); foreach ($hmatches[1] as $hmatch) { $tag = common_canonical_tag($hmatch[0]); $plist = Profile_list::getByTaggerAndTag($sender->id, $tag); if (!empty($plist) && !$plist->private) { $tagged = $sender->getTaggedSubscribers($tag); $url = common_local_url('showprofiletag', array('tagger' => $sender->nickname, 'tag' => $tag)); $mentions[] = array('mentioned' => $tagged, 'text' => $hmatch[0], 'position' => $hmatch[1], 'url' => $url); } } Event::handle('EndFindMentions', array($sender, $text, &$mentions)); } return $mentions; }
/** * Check whether the given URL represents one of our canonical * user or group Atom feeds. * * @param string $feed URL * @return boolean true if it matches */ function recognizedFeed($feed) { $matches = array(); if (preg_match('!/(\\d+)\\.atom$!', $feed, $matches)) { $id = $matches[1]; $params = array('id' => $id, 'format' => 'atom'); $userFeed = common_local_url('ApiTimelineUser', $params); $groupFeed = common_local_url('ApiTimelineGroup', $params); if ($feed == $userFeed) { $user = User::staticGet('id', $id); if (!$user) { // TRANS: Client exception. %s is a feed URL. throw new ClientException(sprintt(_m('Invalid hub.topic "%s". User does not exist.'), $feed)); } else { return true; } } if ($feed == $groupFeed) { $user = User_group::staticGet('id', $id); if (!$user) { // TRANS: Client exception. %s is a feed URL. throw new ClientException(sprintf(_m('Invalid hub.topic "%s". Group does not exist.'), $feed)); } else { return true; } } } else { if (preg_match('!/(\\d+)/lists/(\\d+)/statuses\\.atom$!', $feed, $matches)) { $user = $matches[1]; $id = $matches[2]; $params = array('user' => $user, 'id' => $id, 'format' => 'atom'); $listFeed = common_local_url('ApiTimelineList', $params); if ($feed == $listFeed) { $list = Profile_list::staticGet('id', $id); $user = User::staticGet('id', $user); if (!$list || !$user || $list->tagger != $user->id) { // TRANS: Client exception. %s is a feed URL. throw new ClientException(sprintf(_m('Invalid hub.topic %s; list does not exist.'), $feed)); } else { return true; } } common_log(LOG_DEBUG, "Not a user, group or people tag feed? {$feed} {$userFeed} {$groupFeed} {$listFeed}"); } } common_log(LOG_DEBUG, "LOST {$feed}"); return false; }
/** * Check whether the given URL represents one of our canonical * user or group Atom feeds. * * @param string $feed URL * @return boolean true if it matches, false if not a recognized local feed * @throws exception if local entity does not exist */ protected function recognizedFeed($feed) { $matches = array(); // Simple mapping to local ID for user or group if (preg_match('!/(\\d+)\\.atom$!', $feed, $matches)) { $id = $matches[1]; $params = array('id' => $id, 'format' => 'atom'); // Double-check against locally generated URLs switch ($feed) { case common_local_url('ApiTimelineUser', $params): $user = User::getKV('id', $id); if (!$user instanceof User) { // TRANS: Client exception. %s is a feed URL. throw new ClientException(sprintf(_m('Invalid hub.topic "%s". User does not exist.'), $feed)); } return true; case common_local_url('ApiTimelineGroup', $params): $group = Local_group::getKV('group_id', $id); if (!$group instanceof Local_group) { // TRANS: Client exception. %s is a feed URL. throw new ClientException(sprintf(_m('Invalid hub.topic "%s". Local_group does not exist.'), $feed)); } return true; } common_debug("Feed was not recognized by any local User or Group Atom feed URLs: {$feed}"); return false; } // Profile lists are unique per user, so we need both IDs if (preg_match('!/(\\d+)/lists/(\\d+)/statuses\\.atom$!', $feed, $matches)) { $user = $matches[1]; $id = $matches[2]; $params = array('user' => $user, 'id' => $id, 'format' => 'atom'); // Double-check against locally generated URLs switch ($feed) { case common_local_url('ApiTimelineList', $params): $list = Profile_list::getKV('id', $id); $user = User::getKV('id', $user); if (!$list instanceof Profile_list || !$user instanceof User || $list->tagger != $user->id) { // TRANS: Client exception. %s is a feed URL. throw new ClientException(sprintf(_m('Invalid hub.topic %s; list does not exist.'), $feed)); } return true; } common_debug("Feed was not recognized by any local Profile_list Atom feed URL: {$feed}"); return false; } common_debug("Unknown feed URL structure, can't match against local user, group or profile_list: {$feed}"); return false; }
function getLists() { $profile = $this->target; $fn = array($profile, 'getOtherTags'); # 20 lists list($this->lists, $this->next_cursor, $this->prev_cursor) = Profile_list::getAtCursor($fn, array($this->auth_user), $this->cursor, 20); }
function getTargetList($user = null, $id = null) { $tagger = $this->getTargetUser($user); $list = null; if (empty($id)) { $id = $this->arg('id'); } if ($id) { if (is_numeric($id)) { $list = Profile_list::staticGet('id', $id); // only if the list with the id belongs to the tagger if (empty($list) || $list->tagger != $tagger->id) { $list = null; } } if (empty($list)) { $tag = common_canonical_tag($id); $list = Profile_list::getByTaggerAndTag($tagger->id, $tag); } if (!empty($list) && $list->private) { if ($this->auth_user->id == $list->tagger) { return $list; } } else { return $list; } } return null; }
/** * get Profile_list objects from the database * given their (tag, tagger) key pairs. * * @param array $keys array of array(tagger, tag) * * @return Profile_list results */ static function getByKeys(array $keys) { $cache = Cache::instance(); if (!empty($cache)) { $tags = array(); foreach ($keys as $key) { $t = Profile_list::getByTaggerAndTag($key[0], $key[1]); if (!empty($t)) { $tags[] = $t; } } return new ArrayWrapper($tags); } else { $tag = new Profile_list(); if (empty($keys)) { //if no IDs requested, just return the tag object return $tag; } $pairs = array(); foreach ($keys as $key) { $pairs[] = '(' . $key[0] . ', "' . $key[1] . '")'; } $tag->whereAdd('(tagger, tag) in (' . implode(', ', $pairs) . ')'); $tag->find(); $temp = array(); while ($tag->fetch()) { $temp[$tag->tagger . '-' . $tag->tag] = clone $tag; } $wrapped = array(); foreach ($keys as $key) { $id = $key[0] . '-' . $key[1]; if (array_key_exists($id, $temp)) { $wrapped[] = $temp[$id]; } } return new ArrayWrapper($wrapped); } }
/** * Create local ostatus_profile and profile/user_group entries for * the provided remote user or group. * This should never return null -- you will either get an object or * an exception will be thrown. * * @param ActivityObject $object * @param array $hints * * @return Ostatus_profile */ protected static function createActivityObjectProfile(ActivityObject $object, array $hints = array()) { $homeuri = $object->id; $discover = false; if (!$homeuri) { common_log(LOG_DEBUG, __METHOD__ . " empty actor profile URI: " . var_export($activity, true)); // TRANS: Exception. throw new Exception(_m('No profile URI.')); } $user = User::getKV('uri', $homeuri); if ($user instanceof User) { // TRANS: Exception. throw new Exception(_m('Local user cannot be referenced as remote.')); } if (OStatusPlugin::localGroupFromUrl($homeuri)) { // TRANS: Exception. throw new Exception(_m('Local group cannot be referenced as remote.')); } $ptag = Profile_list::getKV('uri', $homeuri); if ($ptag instanceof Profile_list) { $local_user = User::getKV('id', $ptag->tagger); if ($local_user instanceof User) { // TRANS: Exception. throw new Exception(_m('Local list cannot be referenced as remote.')); } } if (array_key_exists('feedurl', $hints)) { $feeduri = $hints['feedurl']; } else { $discover = new FeedDiscovery(); $feeduri = $discover->discoverFromURL($homeuri); } if (array_key_exists('salmon', $hints)) { $salmonuri = $hints['salmon']; } else { if (!$discover) { $discover = new FeedDiscovery(); $discover->discoverFromFeedURL($hints['feedurl']); } // XXX: NS_REPLIES is deprecated anyway, so let's remove it in the future. $salmonuri = $discover->getAtomLink(Salmon::REL_SALMON) ?: $discover->getAtomLink(Salmon::NS_REPLIES); } if (array_key_exists('hub', $hints)) { $huburi = $hints['hub']; } else { if (!$discover) { $discover = new FeedDiscovery(); $discover->discoverFromFeedURL($hints['feedurl']); } $huburi = $discover->getHubLink(); } if (!$huburi && !common_config('feedsub', 'fallback_hub') && !common_config('feedsub', 'nohub')) { // We can only deal with folks with a PuSH hub throw new FeedSubNoHubException(); } $oprofile = new Ostatus_profile(); $oprofile->uri = $homeuri; $oprofile->feeduri = $feeduri; $oprofile->salmonuri = $salmonuri; $oprofile->created = common_sql_now(); $oprofile->modified = common_sql_now(); if ($object->type == ActivityObject::PERSON) { $profile = new Profile(); $profile->created = common_sql_now(); self::updateProfile($profile, $object, $hints); $oprofile->profile_id = $profile->insert(); if ($oprofile->profile_id === false) { // TRANS: Server exception. throw new ServerException(_m('Cannot save local profile.')); } } else { if ($object->type == ActivityObject::GROUP) { $profile = new Profile(); $profile->query('BEGIN'); $group = new User_group(); $group->uri = $homeuri; $group->created = common_sql_now(); self::updateGroup($group, $object, $hints); // TODO: We should do this directly in User_group->insert()! // currently it's duplicated in User_group->update() // AND User_group->register()!!! $fields = array('nickname' => 'nickname', 'fullname' => 'fullname', 'mainpage' => 'profileurl', 'homepage' => 'homepage', 'description' => 'bio', 'location' => 'location', 'created' => 'created', 'modified' => 'modified'); foreach ($fields as $gf => $pf) { $profile->{$pf} = $group->{$gf}; } $profile_id = $profile->insert(); if ($profile_id === false) { $profile->query('ROLLBACK'); throw new ServerException(_('Profile insertion failed.')); } $group->profile_id = $profile_id; $oprofile->group_id = $group->insert(); if ($oprofile->group_id === false) { $profile->query('ROLLBACK'); // TRANS: Server exception. throw new ServerException(_m('Cannot save local profile.')); } $profile->query('COMMIT'); } else { if ($object->type == ActivityObject::_LIST) { $ptag = new Profile_list(); $ptag->uri = $homeuri; $ptag->created = common_sql_now(); self::updatePeopletag($ptag, $object, $hints); $oprofile->peopletag_id = $ptag->insert(); if ($oprofile->peopletag_id === false) { // TRANS: Server exception. throw new ServerException(_m('Cannot save local list.')); } } } } $ok = $oprofile->insert(); if ($ok === false) { // TRANS: Server exception. throw new ServerException(_m('Cannot save OStatus profile.')); } $avatar = self::getActivityObjectAvatar($object, $hints); if ($avatar) { try { $oprofile->updateAvatar($avatar); } catch (Exception $ex) { // Profile is saved, but Avatar is messed up. We're // just going to continue. common_log(LOG_WARNING, "Exception saving OStatus profile avatar: " . $ex->getMessage()); } } return $oprofile; }
/** * List the members of a list (people tagged) */ function getUsers() { $fn = array($this->list, 'getTagged'); list($this->users, $this->next_cursor, $this->prev_cursor) = Profile_list::getAtCursor($fn, array(), $this->cursor, 20); }