function handle($notice) { assert($notice instanceof Notice); $this->notice = $notice; $this->user = User::staticGet($notice->profile_id); $this->pushUser(); foreach ($notice->getGroups() as $group) { $oprofile = Ostatus_profile::staticGet('group_id', $group->id); if ($oprofile) { $this->pingReply($oprofile); } else { $this->pushGroup($group->id); } } foreach ($notice->getReplies() as $profile_id) { $oprofile = Ostatus_profile::staticGet('profile_id', $profile_id); if ($oprofile) { $this->pingReply($oprofile); } } if (!empty($this->notice->reply_to)) { $replyTo = Notice::staticGet('id', $this->notice->reply_to); if (!empty($replyTo)) { foreach ($replyTo->getReplies() as $profile_id) { $oprofile = Ostatus_profile::staticGet('profile_id', $profile_id); if ($oprofile) { $this->pingReply($oprofile); } } } } return true; }
function onStartHandleFeedEntry($activity) { common_log(LOG_INFO, 'photo plugin: onEndAtomPubNewActivity'); $oprofile = Ostatus_profile::ensureActorProfile($activity); foreach ($activity->objects as $object) { if ($object->type == ActivityObject::PHOTO) { $uri = $object->largerImage; $thumb_uri = $object->thumbnail; $profile_id = $oprofile->profile_id; $source = 'unknown'; // TODO: put something better here. common_log(LOG_INFO, 'uri : ' . $uri); common_log(LOG_INFO, 'thumb_uri : ' . $thumb_uri); // It's possible this is validated elsewhere, but I'm not sure and // would rather be safe. $uri = filter_var($uri, FILTER_SANITIZE_URL); $thumb_uri = filter_var($thumb_uri, FILTER_SANITIZE_URL); $uri = filter_var($uri, FILTER_VALIDATE_URL); $thumb_uri = filter_var($thumb_uri, FILTER_VALIDATE_URL); if (empty($thumb_uri)) { // We need a thumbnail, so if we aren't given one, use the actual picture for now. $thumb_uri = $uri; } if (!empty($uri) && !empty($thumb_uri)) { GNUsocialPhoto::saveNew($profile_id, $thumb_uri, $uri, $source, false); } else { common_log(LOG_INFO, 'bad URI for photo'); } return false; } } return true; }
function prepare($args) { parent::prepare($args); $id = $this->trimmed('id'); if (!$id) { $this->clientError(_('No ID.')); } $this->group = User_group::staticGet('id', $id); if (empty($this->group)) { $this->clientError(_('No such group.')); } $oprofile = Ostatus_profile::staticGet('group_id', $id); if ($oprofile) { $this->clientError(_m("Can't accept remote posts for a remote group.")); } return true; }
function handle($notice) { assert($notice instanceof Notice); $this->notice = $notice; $this->user = User::staticGet('id', $notice->profile_id); try { $profile = $this->notice->getProfile(); } catch (Exception $e) { common_log(LOG_ERR, "Can't get profile for notice; skipping: " . $e->getMessage()); return true; } $this->pushUser(); foreach ($notice->getGroups() as $group) { $oprofile = Ostatus_profile::staticGet('group_id', $group->id); if ($oprofile) { $this->pingReply($oprofile); } else { $this->pushGroup($group->id); } } foreach ($notice->getReplies() as $profile_id) { $oprofile = Ostatus_profile::staticGet('profile_id', $profile_id); if ($oprofile) { $this->pingReply($oprofile); } } if (!empty($this->notice->reply_to)) { $replyTo = Notice::staticGet('id', $this->notice->reply_to); if (!empty($replyTo)) { foreach ($replyTo->getReplies() as $profile_id) { $oprofile = Ostatus_profile::staticGet('profile_id', $profile_id); if ($oprofile) { $this->pingReply($oprofile); } } } } foreach ($notice->getProfileTags() as $ptag) { $oprofile = Ostatus_profile::staticGet('peopletag_id', $ptag->id); if (!$oprofile) { $this->pushPeopletag($ptag); } } 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; }
protected function prepare(array $args = array()) { parent::prepare($args); $id = $this->trimmed('id'); if (!$id) { // TRANS: Client error. $this->clientError(_m('No ID.')); } $this->group = User_group::getKV('id', $id); if (!$this->group instanceof User_group) { // TRANS: Client error. $this->clientError(_m('No such group.')); } $this->target = $this->group; $remote_group = Ostatus_profile::getKV('group_id', $id); if ($remote_group instanceof Ostatus_profile) { // TRANS: Client error. $this->clientError(_m('Cannot accept remote posts for a remote group.')); } 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 fixProfile($uri) { $oprofile = Ostatus_profile::getKV('uri', $uri); if (!$oprofile) { print "No OStatus remote profile known for URI {$uri}\n"; return false; } echo "Before:\n"; showProfileInfo($oprofile); $feedurl = $oprofile->feeduri; $client = new HttpClient(); $response = $client->get($feedurl); if ($response->isOk()) { echo "Updating profile from feed: {$feedurl}\n"; $dom = new DOMDocument(); if ($dom->loadXML($response->getBody())) { $feed = $dom->documentElement; $entries = $dom->getElementsByTagNameNS(Activity::ATOM, 'entry'); if ($entries->length) { $entry = $entries->item(0); $activity = new Activity($entry, $feed); $oprofile->checkAuthorship($activity); echo " (ok)\n"; } else { echo " (no entry; skipping)\n"; return false; } } else { echo " (bad feed; skipping)\n"; return false; } } else { echo "Failed feed fetch: {$response->getStatus()} for {$feedurl}\n"; return false; } echo "After:\n"; showProfileInfo($oprofile); return true; }
function handle($object) { list($user, $remote, $password) = $object; $remote = Discovery::normalize($remote); $oprofile = Ostatus_profile::ensureProfileURI($remote); if (empty($oprofile)) { // TRANS: Exception thrown when an account could not be located when it should be moved. // TRANS: %s is the remote site. throw new Exception(sprintf(_("Cannot locate account %s."), $remote)); } list($svcDocUrl, $username) = self::getServiceDocument($remote); $sink = new ActivitySink($svcDocUrl, $username, $password); $this->log(LOG_INFO, "Moving user {$user->nickname} " . "to {$remote}."); $stream = new UserActivityStream($user); // Reverse activities to run in correct chron order $acts = array_reverse($stream->activities); $this->log(LOG_INFO, "Got " . count($acts) . " activities " . "for {$user->nickname}."); $qm = QueueManager::get(); foreach ($acts as $act) { $qm->enqueue(array($act, $sink, $user->uri, $remote), 'actmove'); } $this->log(LOG_INFO, "Finished moving user {$user->nickname} " . "to {$remote}."); }
/** * Create the initial admin user account. * Side effect: may load portions of StatusNet framework. * Side effect: outputs program info */ function registerInitialUser() { define('STATUSNET', true); define('LACONICA', true); // compatibility require_once INSTALLDIR . '/lib/common.php'; $data = array('nickname' => $this->adminNick, 'password' => $this->adminPass, 'fullname' => $this->adminNick); if ($this->adminEmail) { $data['email'] = $this->adminEmail; } $user = User::register($data); if (empty($user)) { return false; } // give initial user carte blanche $user->grantRole('owner'); $user->grantRole('moderator'); $user->grantRole('administrator'); // Attempt to do a remote subscribe to update@status.net // Will fail if instance is on a private network. if ($this->adminUpdates && class_exists('Ostatus_profile')) { try { $oprofile = Ostatus_profile::ensureProfileURL('http://update.status.net/'); Subscription::start($user->getProfile(), $oprofile->localProfile()); $this->updateStatus("Set up subscription to <a href='http://update.status.net/'>update@status.net</a>."); } catch (Exception $e) { $this->updateStatus("Could not set up subscription to <a href='http://update.status.net/'>update@status.net</a>.", true); } } return true; }
static function ensureProfileURI($uri) { $oprofile = null; // First, try to query it $oprofile = Ostatus_profile::staticGet('uri', $uri); // If unfound, do discovery stuff if (empty($oprofile)) { if (preg_match("/^(\\w+)\\:(.*)/", $uri, $match)) { $protocol = $match[1]; switch ($protocol) { case 'http': case 'https': $oprofile = Ostatus_profile::ensureProfileURL($uri); break; case 'acct': case 'mailto': $rest = $match[2]; $oprofile = Ostatus_profile::ensureWebfinger($rest); break; default: throw new ServerException("Unrecognized URI protocol for profile: {$protocol} ({$uri})"); break; } } else { throw new ServerException("No URI protocol for profile: ({$uri})"); } } return $oprofile; }
private function getFeed($profile) { // Ok this is a bit of a hack. ;) if (class_exists('Ostatus_profile')) { $oprofile = Ostatus_profile::staticGet('profile_id', $profile->id); if ($oprofile) { return $oprofile->feeduri; } } var_dump('wtf'); return false; }
function onStartGetProfileFromURI($uri, &$profile) { // Don't want to do Web-based discovery on our own server, // so we check locally first. $user = User::staticGet('uri', $uri); if (!empty($user)) { $profile = $user->getProfile(); return false; } // Now, check remotely $oprofile = Ostatus_profile::ensureProfileURI($uri); if (!empty($oprofile)) { $profile = $oprofile->localProfile(); return false; } // Still not a hit, so give up. return true; }
/** * Ping remote profiles with updates to this profile. * Salmon pings are queued for background processing. */ function onEndBroadcastProfile(Profile $profile) { $user = User::staticGet('id', $profile->id); // Find foreign accounts I'm subscribed to that support Salmon pings. // // @fixme we could run updates through the PuSH feed too, // in which case we can skip Salmon pings to folks who // are also subscribed to me. $sql = "SELECT * FROM ostatus_profile " . "WHERE profile_id IN " . "(SELECT subscribed FROM subscription WHERE subscriber=%d) " . "OR group_id IN " . "(SELECT group_id FROM group_member WHERE profile_id=%d)"; $oprofile = new Ostatus_profile(); $oprofile->query(sprintf($sql, $profile->id, $profile->id)); if ($oprofile->N == 0) { common_log(LOG_DEBUG, "No OStatus remote subscribees for {$profile->nickname}"); return true; } $act = new Activity(); $act->verb = ActivityVerb::UPDATE_PROFILE; $act->id = TagURI::mint('update-profile:%d:%s', $profile->id, common_date_iso8601(time())); $act->time = time(); $act->title = _m("Profile update"); $act->content = sprintf(_m("%s has updated their profile page."), $profile->getBestName()); $act->actor = ActivityObject::fromProfile($profile); $act->object = $act->actor; while ($oprofile->fetch()) { $oprofile->notifyDeferred($act, $profile); } return true; }
/** * Look up, and if necessary create, an Ostatus_profile for the remote * entity with the given webfinger address. * This should never return null -- you will either get an object or * an exception will be thrown. * * @param string $addr webfinger address * @return Ostatus_profile * @throws Exception on error conditions * @throws OStatusShadowException if this reference would obscure a local user/group */ public static function ensureWebfinger($addr) { // First, try the cache $uri = self::cacheGet(sprintf('ostatus_profile:webfinger:%s', $addr)); if ($uri !== false) { if (is_null($uri)) { // Negative cache entry throw new Exception('Not a valid webfinger address.'); } $oprofile = Ostatus_profile::staticGet('uri', $uri); if (!empty($oprofile)) { return $oprofile; } } // Try looking it up $oprofile = Ostatus_profile::staticGet('uri', 'acct:' . $addr); if (!empty($oprofile)) { self::cacheSet(sprintf('ostatus_profile:webfinger:%s', $addr), $oprofile->uri); return $oprofile; } // Now, try some discovery $disco = new Discovery(); try { $xrd = $disco->lookup($addr); } catch (Exception $e) { // Save negative cache entry so we don't waste time looking it up again. // @fixme distinguish temporary failures? self::cacheSet(sprintf('ostatus_profile:webfinger:%s', $addr), null); throw new Exception('Not a valid webfinger address.'); } $hints = array('webfinger' => $addr); $dhints = DiscoveryHints::fromXRD($xrd); $hints = array_merge($hints, $dhints); // If there's an Hcard, let's grab its info if (array_key_exists('hcard', $hints)) { if (!array_key_exists('profileurl', $hints) || $hints['hcard'] != $hints['profileurl']) { $hcardHints = DiscoveryHints::fromHcardUrl($hints['hcard']); $hints = array_merge($hcardHints, $hints); } } // If we got a feed URL, try that if (array_key_exists('feedurl', $hints)) { try { common_log(LOG_INFO, "Discovery on acct:{$addr} with feed URL " . $hints['feedurl']); $oprofile = self::ensureFeedURL($hints['feedurl'], $hints); self::cacheSet(sprintf('ostatus_profile:webfinger:%s', $addr), $oprofile->uri); return $oprofile; } catch (Exception $e) { common_log(LOG_WARNING, "Failed creating profile from feed URL '{$feedUrl}': " . $e->getMessage()); // keep looking } } // If we got a profile page, try that! if (array_key_exists('profileurl', $hints)) { try { common_log(LOG_INFO, "Discovery on acct:{$addr} with profile URL {$profileUrl}"); $oprofile = self::ensureProfileURL($hints['profileurl'], $hints); self::cacheSet(sprintf('ostatus_profile:webfinger:%s', $addr), $oprofile->uri); return $oprofile; } catch (OStatusShadowException $e) { // We've ended up with a remote reference to a local user or group. // @fixme ideally we should be able to say who it was so we can // go back and refer to it the regular way throw $e; } catch (Exception $e) { common_log(LOG_WARNING, "Failed creating profile from profile URL '{$profileUrl}': " . $e->getMessage()); // keep looking // // @fixme this means an error discovering from profile page // may give us a corrupt entry using the webfinger URI, which // will obscure the correct page-keyed profile later on. } } // XXX: try hcard // XXX: try FOAF if (array_key_exists('salmon', $hints)) { $salmonEndpoint = $hints['salmon']; // An account URL, a salmon endpoint, and a dream? Not much to go // on, but let's give it a try $uri = 'acct:' . $addr; $profile = new Profile(); $profile->nickname = self::nicknameFromUri($uri); $profile->created = common_sql_now(); if (isset($profileUrl)) { $profile->profileurl = $profileUrl; } $profile_id = $profile->insert(); if (!$profile_id) { common_log_db_error($profile, 'INSERT', __FILE__); throw new Exception("Couldn't save profile for '{$addr}'"); } $oprofile = new Ostatus_profile(); $oprofile->uri = $uri; $oprofile->salmonuri = $salmonEndpoint; $oprofile->profile_id = $profile_id; $oprofile->created = common_sql_now(); if (isset($feedUrl)) { $profile->feeduri = $feedUrl; } $result = $oprofile->insert(); if (!$result) { common_log_db_error($oprofile, 'INSERT', __FILE__); throw new Exception("Couldn't save ostatus_profile for '{$addr}'"); } self::cacheSet(sprintf('ostatus_profile:webfinger:%s', $addr), $oprofile->uri); return $oprofile; } throw new Exception("Couldn't find a valid profile for '{$addr}'"); }
/** * Handle a posted object from Salmon * * @param Activity $activity activity to handle * @param mixed $target user or group targeted * * @return boolean hook value */ function onStartHandleSalmonTarget(Activity $activity, $target) { if (!$this->isMyActivity($activity)) { return true; } $this->log(LOG_INFO, "Checking {$activity->id} as a valid Salmon slap."); if ($target instanceof User_group || $target->isGroup()) { $uri = $target->getUri(); if (!array_key_exists($uri, $activity->context->attention)) { // @todo FIXME: please document (i18n). // TRANS: Client exception thrown when ... throw new ClientException(_('Object not posted to this group.')); } } elseif ($target instanceof Profile && $target->isLocal()) { $original = null; // FIXME: Shouldn't favorites show up with a 'target' activityobject? if (!ActivityUtils::compareTypes($activity->verb, array(ActivityVerb::POST)) && isset($activity->objects[0])) { // If this is not a post, it's a verb targeted at something (such as a Favorite attached to a note) if (!empty($activity->objects[0]->id)) { $activity->context->replyToID = $activity->objects[0]->id; } } if (!empty($activity->context->replyToID)) { $original = Notice::getKV('uri', $activity->context->replyToID); } if ((!$original instanceof Notice || $original->profile_id != $target->id) && !array_key_exists($target->getUri(), $activity->context->attention)) { // @todo FIXME: Please document (i18n). // TRANS: Client exception when ... throw new ClientException(_('Object not posted to this user.')); } } else { // TRANS: Server exception thrown when a micro app plugin uses a target that cannot be handled. throw new ServerException(_('Do not know how to handle this kind of target.')); } $oactor = Ostatus_profile::ensureActivityObjectProfile($activity->actor); $actor = $oactor->localProfile(); // FIXME: will this work in all cases? I made it work for Favorite... if (ActivityUtils::compareTypes($activity->verb, array(ActivityVerb::POST))) { $object = $activity->objects[0]; } else { $object = $activity; } $options = array('uri' => $object->id, 'url' => $object->link, 'is_local' => Notice::REMOTE, 'source' => 'ostatus'); if (!isset($this->oldSaveNew)) { $notice = Notice::saveActivity($activity, $actor, $options); } else { $notice = $this->saveNoticeFromActivity($activity, $actor, $options); } return false; }
/** * * @param string $url * @return Profile */ protected function profileForFeed($url) { try { // Maybe we got a web page? $oprofile = Ostatus_profile::ensureProfileURL($url); } catch (Exception $e) { // Direct feed URL? $oprofile = Ostatus_profile::ensureFeedURL($url); } if ($oprofile->isGroup()) { // TRANS: Client error displayed when trying to mirror a StatusNet group feed. $this->clientError(_m('Cannot mirror a StatusNet group at this time.')); } $this->oprofile = $oprofile; // @todo FIXME: ugly side effect :D return $oprofile->localProfile(); }
protected function filterAttention(array $attn) { $groups = array(); // TODO: context->attention $replies = array(); // TODO: context->attention foreach ($attn as $recipient => $type) { // Is the recipient a local user? $user = User::getKV('uri', $recipient); if ($user instanceof User) { // TODO: @fixme sender verification, spam etc? $replies[] = $recipient; continue; } // Is the recipient a remote group? $oprofile = Ostatus_profile::ensureProfileURI($recipient); if ($oprofile) { if (!$oprofile->isGroup()) { // may be canonicalized or something $replies[] = $oprofile->uri; } continue; } // Is the recipient a local group? // TODO: @fixme uri on user_group isn't reliable yet // $group = User_group::getKV('uri', $recipient); $id = OStatusPlugin::localGroupFromUrl($recipient); if ($id) { $group = User_group::getKV('id', $id); if ($group) { // Deliver to all members of this local group if allowed. $profile = $sender->localProfile(); if ($profile->isMember($group)) { $groups[] = $group->id; } else { common_log(LOG_INFO, "Skipping reply to local group {$group->nickname} as sender {$profile->id} is not a member"); } continue; } else { common_log(LOG_INFO, "Skipping reply to bogus group {$recipient}"); } } } return array($groups, $replies); }
function updateOStatus($user) { if (!have_option('q', 'quiet')) { echo "{$user->nickname}..."; } $up = $user->getProfile(); $sp = $user->getSubscriptions(); $rps = array(); while ($sp->fetch()) { $remote = Remote_profile::staticGet('id', $sp->id); if (!empty($remote)) { $rps[] = clone $sp; } } if (!have_option('q', 'quiet')) { echo count($rps) . "\n"; } foreach ($rps as $rp) { try { if (!have_option('q', 'quiet')) { echo "Checking {$rp->nickname}..."; } $op = Ostatus_profile::ensureProfileURL($rp->profileurl); if (empty($op)) { echo "can't convert.\n"; continue; } else { if (!have_option('q', 'quiet')) { echo "Converting..."; } Subscription::start($up, $op->localProfile()); Subscription::cancel($up, $rp); if (!have_option('q', 'quiet')) { echo "done.\n"; } } } catch (Exception $e) { if (!have_option('q', 'quiet')) { echo "fail.\n"; } common_log(LOG_NOTICE, "Couldn't convert OMB subscription (" . $up->nickname . ", " . $rp->nickname . ") to OStatus: " . $e->getMessage()); continue; } } }
/** * Checks for deleted remote notices and deleted the locally * A local qvitter-delete-notice is outputted in the onNoticeDeleteRelated event above * * @return boolean hook flag */ public function onEndHandleFeedEntry($activity) { if ($activity->verb == 'qvitter-delete-notice' && class_exists('StatusNet') && !array_key_exists('ActivityModeration', StatusNet::getActivePlugins())) { $deleter_profile_uri = $activity->actor->id; $deleted_notice_uri = $activity->objects[0]->objects[0]->content; $deleted_notice_uri = substr($deleted_notice_uri, strpos($deleted_notice_uri, '{{') + 2); $deleted_notice_uri = substr($deleted_notice_uri, 0, strpos($deleted_notice_uri, '}}')); $deleter_ostatus_profile = Ostatus_profile::getKV('uri', $deleter_profile_uri); if (!$deleter_ostatus_profile instanceof Ostatus_profile) { return true; } $deleter_profile = Profile::getKV('id', $deleter_ostatus_profile->profile_id); $deleted_notice = Notice::getKV('uri', $deleted_notice_uri); if (!$deleter_profile instanceof Profile || !$deleted_notice instanceof Notice) { return true; } if ($deleter_profile->id != $deleted_notice->profile_id) { return true; } $deleted_notice->delete(); } return true; }
print "Failed to update sub record...\n"; exit(1); } } else { print "\n"; print "Feed record ok, not changing.\n\n"; } echo "\n"; echo "Pinging hub {$sub->huburi} with new subscription for {$sub->uri}\n"; try { $sub->subscribe(); echo "ok\n"; } catch (Exception $e) { echo 'Could not confirm. ' . get_class($e) . ': ' . $e->getMessage() . "\n"; } $o2 = Ostatus_profile::getKV('uri', $uri); print "\n"; print "New profile state:\n"; showProfile($o2); print "\n"; print "New feed state:\n"; $sub2 = FeedSub::ensureFeed($feedurl); showSub($sub2); function showProfile($oprofile) { print " Feed URL: {$oprofile->feeduri}\n"; print " Salmon URL: {$oprofile->salmonuri}\n"; print " Avatar URL: {$oprofile->avatar}\n"; print " Profile ID: {$oprofile->profile_id}\n"; print " Group ID: {$oprofile->group_id}\n"; print " Record created: {$oprofile->created}\n";
print "Failed to update sub record...\n"; exit(1); } } else { print "\n"; print "Feed record ok, not changing.\n\n"; } print "\n"; print "Pinging hub {$sub->huburi} with new subscription for {$sub->uri}\n"; $ok = $sub->subscribe(); if ($ok) { print "ok\n"; } else { print "Could not confirm.\n"; } $o2 = Ostatus_profile::staticGet('uri', $uri); print "\n"; print "New profile state:\n"; showProfile($o2); print "\n"; print "New feed state:\n"; $sub2 = FeedSub::ensureFeed($feedurl); showSub($sub2); function showProfile($oprofile) { print " Feed URL: {$oprofile->feeduri}\n"; print " Salmon URL: {$oprofile->salmonuri}\n"; print " Avatar URL: {$oprofile->avatar}\n"; print " Profile ID: {$oprofile->profile_id}\n"; print " Group ID: {$oprofile->group_id}\n"; print " Record created: {$oprofile->created}\n";
/** * Let the OStatus subscription garbage collection know if we're * making use of a remote feed, so it doesn't get dropped out * from under us. * * @param Ostatus_profile $oprofile * @param int $count in/out * @return mixed hook return value */ function onOstatus_profileSubscriberCount(Ostatus_profile $oprofile, &$count) { try { $profile = $oprofile->localProfile(); $mirror = new SubMirror(); $mirror->subscribed = $profile->id; if ($mirror->find()) { while ($mirror->fetch()) { $count++; } } } catch (NoProfileException $e) { // We can't handle this kind of Ostatus_profile since it has no // local profile } return true; }
} echo "local group {$id} ({$local->nickname}) hidden by {$uri} (bogus group id {$group->id})"; if ($dry) { echo " - skipping\n"; } else { echo " - removing bogus user_group entry..."; $evil = User_group::staticGet('id', $group->id); $evil->delete(); echo " ok\n"; } } } echo "\n"; // Fallback? echo "Checking for bogus profiles blocking local users/groups by URI pattern match...\n"; $oprofile = new Ostatus_profile(); $marker = mt_rand(31337, 31337000); $profileTemplate = common_local_url('userbyid', array('id' => $marker)); $encProfile = $oprofile->escape($profileTemplate, true); $encProfile = str_replace($marker, '%', $encProfile); echo " LIKE '{$encProfile}'\n"; $groupTemplate = common_local_url('groupbyid', array('id' => $marker)); $encGroup = $oprofile->escape($groupTemplate, true); $encGroup = str_replace($marker, '%', $encGroup); echo " LIKE '{$encGroup}'\n"; $sql = "SELECT * FROM ostatus_profile WHERE uri LIKE '%s' OR uri LIKE '%s'"; $oprofile->query(sprintf($sql, $encProfile, $encGroup)); $count = $oprofile->N; echo "Found {$count}...\n"; while ($oprofile->fetch()) { $uri = $oprofile->uri;
/** * Pull data for a remote profile and check if it's valid. * Fills out error UI string in $this->error * Fills out $this->oprofile on success. * * @return boolean */ function pullRemoteProfile() { $this->profile_uri = $this->trimmed('profile'); try { if (Validate::email($this->profile_uri)) { $this->oprofile = Ostatus_profile::ensureWebfinger($this->profile_uri); } else { if (Validate::uri($this->profile_uri)) { $this->oprofile = Ostatus_profile::ensureProfileURL($this->profile_uri); } else { // TRANS: Error message in OStatus plugin. Do not translate the domain names example.com // TRANS: and example.net, as these are official standard domain names for use in examples. $this->error = _m("Sorry, we could not reach that address. Please make sure that the OStatus address is like nickname@example.com or http://example.net/nickname."); common_debug('Invalid address format.', __FILE__); return false; } } return true; } catch (FeedSubBadURLException $e) { // TRANS: Error message in OStatus plugin. Do not translate the domain names example.com // TRANS: and example.net, as these are official standard domain names for use in examples. $this->error = _m('Sorry, we could not reach that address. Please make sure that the OStatus address is like nickname@example.com or http://example.net/nickname.'); common_debug('Invalid URL or could not reach server.', __FILE__); } catch (FeedSubBadResponseException $e) { // TRANS: Error text. $this->error = _m('Sorry, we could not reach that feed. Please try that OStatus address again later.'); common_debug('Cannot read feed; server returned error.', __FILE__); } catch (FeedSubEmptyException $e) { // TRANS: Error text. $this->error = _m('Sorry, we could not reach that feed. Please try that OStatus address again later.'); common_debug('Cannot read feed; server returned an empty page.', __FILE__); } catch (FeedSubBadHTMLException $e) { // TRANS: Error text. $this->error = _m('Sorry, we could not reach that feed. Please try that OStatus address again later.'); common_debug('Bad HTML, could not find feed link.', __FILE__); } catch (FeedSubNoFeedException $e) { // TRANS: Error text. $this->error = _m("Sorry, we could not reach that feed. Please try that OStatus address again later."); common_debug('Could not find a feed linked from this URL.', __FILE__); } catch (FeedSubUnrecognizedTypeException $e) { // TRANS: Error text. $this->error = _m("Sorry, we could not reach that feed. Please try that OStatus address again later."); common_debug('Not a recognized feed type.', __FILE__); } catch (Exception $e) { // Any new ones we forgot about // TRANS: Error message in OStatus plugin. Do not translate the domain names example.com // TRANS: and example.net, as these are official standard domain names for use in examples. $this->error = _m("Sorry, we could not reach that address. Please make sure that the OStatus address is like nickname@example.com or http://example.net/nickname."); common_debug(sprintf('Bad feed URL: %s %s', get_class($e), $e->getMessage()), __FILE__); } return false; }
/** * Checks for deleted remote notices and deleted the locally * A local qvitter-delete-notice is outputted in the onNoticeDeleteRelated event above * * @return boolean hook flag */ public function onEndHandleFeedEntry($activity) { if ($activity->verb == 'qvitter-delete-notice') { $deleter_profile_uri = $activity->actor->id; $deleted_notice_uri = $activity->objects[0]->objects[0]->content; $deleted_notice_uri = substr($deleted_notice_uri, strpos($deleted_notice_uri, '{{') + 2); $deleted_notice_uri = substr($deleted_notice_uri, 0, strpos($deleted_notice_uri, '}}')); $deleter_ostatus_profile = Ostatus_profile::getKV('uri', $deleter_profile_uri); if (!$deleter_ostatus_profile instanceof Ostatus_profile) { return true; } $deleter_profile = Profile::getKV('id', $deleter_ostatus_profile->profile_id); $deleted_notice = Notice::getKV('uri', $deleted_notice_uri); if (!$deleter_profile instanceof Profile || !$deleted_notice instanceof Notice) { return true; } if ($deleter_profile->id != $deleted_notice->profile_id) { return true; } $deleted_notice->delete(); } return true; }
/** * @return Ostatus_profile */ function ensureProfile() { $actor = $this->act->actor; if (empty($actor->id)) { common_log(LOG_ERR, "broken actor: " . var_export($actor, true)); common_log(LOG_ERR, "activity with no actor: " . var_export($this->act, true)); throw new Exception("Received a salmon slap from unidentified actor."); } return Ostatus_profile::ensureActivityObjectProfile($actor); }
function saveMirror() { $mirror = SubMirror::getMirror($this->user, $this->profile); if (!$mirror) { $this->clientError(_m('Requested edit of missing mirror')); } if ($this->delete) { $mirror->delete(); $oprofile = Ostatus_profile::staticGet('profile_id', $this->profile->id); if ($oprofile) { $oprofile->garbageCollect(); } } else { if ($this->style != $mirror->style) { $orig = clone $mirror; $mirror->style = $this->style; $mirror->modified = common_sql_now(); $mirror->update($orig); } } }
static function ensureProfileURI($uri) { $oprofile = null; // First, try to query it $oprofile = Ostatus_profile::getKV('uri', $uri); if ($oprofile instanceof Ostatus_profile) { return $oprofile; } // If unfound, do discovery stuff if (preg_match("/^(\\w+)\\:(.*)/", $uri, $match)) { $protocol = $match[1]; switch ($protocol) { case 'http': case 'https': $oprofile = self::ensureProfileURL($uri); break; case 'acct': case 'mailto': $rest = $match[2]; $oprofile = self::ensureWebfinger($rest); break; default: // TRANS: Server exception. // TRANS: %1$s is a protocol, %2$s is a URI. throw new ServerException(sprintf(_m('Unrecognized URI protocol for profile: %1$s (%2$s).'), $protocol, $uri)); } } else { // TRANS: Server exception. %s is a URI. throw new ServerException(sprintf(_m('No URI protocol for profile: %s.'), $uri)); } return $oprofile; }
function onStartGetProfileFromURI($uri, &$profile) { // XXX: do discovery here instead (OStatus_profile::ensureProfileURI($uri)) $oprofile = Ostatus_profile::staticGet('uri', $uri); if (!empty($oprofile) && !$oprofile->isGroup()) { $profile = $oprofile->localProfile(); return false; } return true; }