From 839b3e7392ac584980a68852e1645b32df4156b7 Mon Sep 17 00:00:00 2001 From: Mikael Nordfeldth Date: Wed, 26 Apr 2017 22:11:28 +0200 Subject: [PATCH 01/11] allowed_schemes was misspelled --- lib/activityutils.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/activityutils.php b/lib/activityutils.php index b86dd65909..0ddb15a749 100644 --- a/lib/activityutils.php +++ b/lib/activityutils.php @@ -294,7 +294,7 @@ class ActivityUtils // Possibly an upstream bug; tag: URIs aren't validated properly // unless you explicitly ask for them. All other schemes are accepted // for basic URI validation without asking. - if ($validate->uri($uri, array('allowed_scheme' => array('tag')))) { + if ($validate->uri($uri, array('allowed_schemes' => array('tag')))) { return true; } From e1df763940b3067ed06a8588ea3a309e6f655341 Mon Sep 17 00:00:00 2001 From: Mikael Nordfeldth Date: Wed, 26 Apr 2017 22:41:59 +0200 Subject: [PATCH 02/11] Test URLs against blacklist also on PuSH subscriptions. --- plugins/Blacklist/BlacklistPlugin.php | 9 +++++++++ plugins/OStatus/actions/pushhub.php | 9 +++++---- 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/plugins/Blacklist/BlacklistPlugin.php b/plugins/Blacklist/BlacklistPlugin.php index bad89f2457..9c73377508 100644 --- a/plugins/Blacklist/BlacklistPlugin.php +++ b/plugins/Blacklist/BlacklistPlugin.php @@ -249,6 +249,15 @@ class BlacklistPlugin extends Plugin return true; } + public function onUrlBlacklistTest($url) + { + common_debug('Checking URL against blacklist: '._ve($url)); + if (!$this->_checkUrl($url)) { + throw new ClientException('Forbidden URL', 403); + } + return true; + } + /** * Helper for checking nicknames * diff --git a/plugins/OStatus/actions/pushhub.php b/plugins/OStatus/actions/pushhub.php index be8076b75e..6dc22706c3 100644 --- a/plugins/OStatus/actions/pushhub.php +++ b/plugins/OStatus/actions/pushhub.php @@ -199,7 +199,7 @@ class PushHubAction extends Action /** * Grab and validate a URL from POST parameters. - * @throws ClientException for malformed or non-http/https URLs + * @throws ClientException for malformed or non-http/https or blacklisted URLs */ protected function argUrl($arg) { @@ -207,13 +207,14 @@ class PushHubAction extends Action $params = array('domain_check' => false, // otherwise breaks my local tests :P 'allowed_schemes' => array('http', 'https')); $validate = new Validate(); - if ($validate->uri($url, $params)) { - return $url; - } else { + if (!$validate->uri($url, $params)) { // TRANS: Client exception. // TRANS: %1$s is this argument to the method this exception occurs in, %2$s is a URL. throw new ClientException(sprintf(_m('Invalid URL passed for %1$s: "%2$s"'),$arg,$url)); } + + Event::handle('UrlBlacklistTest', array($url)); + return $url; } /** From 985f3b44b7378d95a5294b85beac6c8506810a48 Mon Sep 17 00:00:00 2001 From: Mikael Nordfeldth Date: Wed, 26 Apr 2017 23:21:13 +0200 Subject: [PATCH 03/11] LRDD blacklisted URL test --- plugins/LRDD/lib/discovery.php | 7 +++++++ plugins/LRDD/lib/lrddmethod.php | 3 +++ 2 files changed, 10 insertions(+) diff --git a/plugins/LRDD/lib/discovery.php b/plugins/LRDD/lib/discovery.php index c8cf3277e2..54e40fe801 100644 --- a/plugins/LRDD/lib/discovery.php +++ b/plugins/LRDD/lib/discovery.php @@ -126,7 +126,14 @@ class Discovery $xrd->loadString($response->getBody()); return $xrd; + + } catch (ClientException $e) { + if ($e->getCode() === 403) { + common_log(LOG_INFO, sprintf('%s: Aborting discovery on URL %s: %s', _ve($class), _ve($uri), _ve($e->getMessage()))); + break; + } } catch (Exception $e) { + common_log(LOG_INFO, sprintf('%s: Failed for %s: %s', _ve($class), _ve($uri), _ve($e->getMessage()))); continue; } } diff --git a/plugins/LRDD/lib/lrddmethod.php b/plugins/LRDD/lib/lrddmethod.php index ee9a24a5da..160c0d73a2 100644 --- a/plugins/LRDD/lib/lrddmethod.php +++ b/plugins/LRDD/lib/lrddmethod.php @@ -32,6 +32,9 @@ abstract class LRDDMethod protected function fetchUrl($url, $method=HTTPClient::METHOD_GET) { + // If we have a blacklist enabled, let's check against it + Event::handle('UrlBlacklistTest', array($url)); + $client = new HTTPClient(); // GAAHHH, this method sucks! How about we make a better HTTPClient interface? From 7da925ca70c74c3466fd0477403109ed40d02175 Mon Sep 17 00:00:00 2001 From: Mikael Nordfeldth Date: Sat, 6 May 2017 11:34:38 +0200 Subject: [PATCH 04/11] Handle selfLink in ActivityObject --- lib/activityobject.php | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/lib/activityobject.php b/lib/activityobject.php index 87eea13727..fc62e5f46c 100644 --- a/lib/activityobject.php +++ b/lib/activityobject.php @@ -102,6 +102,7 @@ class ActivityObject public $content; public $owner; public $link; + public $selfLink; // think APP (Atom Publishing Protocol) public $source; public $avatarLinks = array(); public $geopoint; @@ -263,6 +264,7 @@ class ActivityObject $this->source = $this->_getSource($element); $this->link = ActivityUtils::getPermalink($element); + $this->selfLink = ActivityUtils::getSelfLink($element); $this->id = $this->_childContent($element, self::ID); @@ -651,6 +653,18 @@ class ActivityObject ); } + if (!empty($this->selfLink)) { + $xo->element( + 'link', + array( + 'rel' => 'self', + 'type' => 'application/atom+xml', + 'href' => $this->selfLink + ), + null + ); + } + if(!empty($this->owner)) { $owner = $this->owner->asActivityNoun(self::AUTHOR); $xo->raw($owner); From 434956fc75d8b9dc4e8ae6547adea5f65796dae4 Mon Sep 17 00:00:00 2001 From: Mikael Nordfeldth Date: Sat, 6 May 2017 12:15:54 +0200 Subject: [PATCH 05/11] Notices start saving selfLink from activities/objects --- classes/Notice.php | 16 ++++++++++++++++ lib/activity.php | 2 +- lib/activityhandlerplugin.php | 3 +++ lib/activityutils.php | 10 ++++++++-- 4 files changed, 28 insertions(+), 3 deletions(-) diff --git a/classes/Notice.php b/classes/Notice.php index a7effe4d5b..3d9968629a 100644 --- a/classes/Notice.php +++ b/classes/Notice.php @@ -59,6 +59,7 @@ class Notice extends Managed_DataObject public $content; // text public $rendered; // text public $url; // varchar(191) not 255 because utf8mb4 takes more space + public $self; // varchar(191) not 255 because utf8mb4 takes more space public $created; // datetime multiple_key not_null default_0000-00-00%2000%3A00%3A00 public $modified; // timestamp not_null default_CURRENT_TIMESTAMP public $reply_to; // int(4) @@ -83,6 +84,7 @@ class Notice extends Managed_DataObject 'content' => array('type' => 'text', 'description' => 'update content', 'collate' => 'utf8mb4_general_ci'), 'rendered' => array('type' => 'text', 'description' => 'HTML version of the content'), 'url' => array('type' => 'varchar', 'length' => 191, 'description' => 'URL of any attachment (image, video, bookmark, whatever)'), + 'self' => array('type' => 'varchar', 'length' => 191, 'description' => 'Resolvable URL to the (remote) Atom entry representation'), 'created' => array('type' => 'datetime', 'not null' => true, 'description' => 'date this record was created'), 'modified' => array('type' => 'timestamp', 'not null' => true, 'description' => 'date this record was modified'), 'reply_to' => array('type' => 'int', 'description' => 'notice replied to (usually a guess)'), @@ -445,6 +447,7 @@ class Notice extends Managed_DataObject static function saveNew($profile_id, $content, $source, array $options=null) { $defaults = array('uri' => null, 'url' => null, + 'self' => null, 'conversation' => null, // URI of conversation 'reply_to' => null, // This will override convo URI if the parent is known 'repeat_of' => null, // This will override convo URI if the repeated notice is known @@ -539,6 +542,9 @@ class Notice extends Managed_DataObject $notice->source = $source; $notice->uri = $uri; $notice->url = $url; + if ($self && common_valid_http_url($self)) { + $notice->self = $self; + } // Get the groups here so we can figure out replies and such if (!isset($groups)) { @@ -776,6 +782,9 @@ class Notice extends Managed_DataObject // implied object $options['uri'] = $act->id; $options['url'] = $act->link; + if ($act->selfLink) { + $options['self'] = $act->selfLink; + } } else { $actobj = count($act->objects)===1 ? $act->objects[0] : null; if (!is_null($actobj) && !empty($actobj->id)) { @@ -786,6 +795,9 @@ class Notice extends Managed_DataObject $options['url'] = $actobj->id; } } + if ($actobj->selfLink) { + $options['self'] = $actobj->selfLink; + } } $defaults = array( @@ -795,6 +807,7 @@ class Notice extends Managed_DataObject 'reply_to' => null, 'repeat_of' => null, 'scope' => null, + 'self' => null, 'source' => 'unknown', 'tags' => array(), 'uri' => null, @@ -847,6 +860,9 @@ class Notice extends Managed_DataObject $stored->source = $source; $stored->uri = $uri; $stored->url = $url; + if (common_valid_http_url($stored->self)) { + $stored->self = $self; + } $stored->verb = $act->verb; $content = $act->content ?: $act->summary; diff --git a/lib/activity.php b/lib/activity.php index b733ff97aa..49f7603d80 100644 --- a/lib/activity.php +++ b/lib/activity.php @@ -267,7 +267,7 @@ class Activity // From APP. Might be useful. - $this->selfLink = ActivityUtils::getLink($entry, 'self', 'application/atom+xml'); + $this->selfLink = ActivityUtils::getSelfLink($entry); $this->editLink = ActivityUtils::getLink($entry, 'edit', 'application/atom+xml'); } diff --git a/lib/activityhandlerplugin.php b/lib/activityhandlerplugin.php index 6e58a05b31..f97bb98aab 100644 --- a/lib/activityhandlerplugin.php +++ b/lib/activityhandlerplugin.php @@ -340,6 +340,7 @@ abstract class ActivityHandlerPlugin extends Plugin $options = array('uri' => $object->id, 'url' => $object->link, + 'self' => $object->selfLink, 'is_local' => Notice::REMOTE, 'source' => 'ostatus'); @@ -416,6 +417,7 @@ abstract class ActivityHandlerPlugin extends Plugin $options = array('uri' => $object->id, 'url' => $object->link, + 'self' => $object->selfLink, 'is_local' => Notice::REMOTE, 'source' => 'ostatus'); @@ -467,6 +469,7 @@ abstract class ActivityHandlerPlugin extends Plugin $options = array('uri' => $object->id, 'url' => $object->link, + 'self' => $object->selfLink, 'source' => 'restore'); // $user->getProfile() is a Profile diff --git a/lib/activityutils.php b/lib/activityutils.php index 0ddb15a749..ba23516ec2 100644 --- a/lib/activityutils.php +++ b/lib/activityutils.php @@ -65,11 +65,16 @@ class ActivityUtils * * @return string related link, if any */ - static function getPermalink($element) + static function getPermalink(DOMNode $element) { return self::getLink($element, 'alternate', 'text/html'); } + static function getSelfLink(DOMNode $element) + { + return self::getLink($element, 'self', 'application/atom+xml'); + } + /** * Get the permalink for an Activity object * @@ -90,8 +95,9 @@ class ActivityUtils $linkRel = $link->getAttribute(self::REL); $linkType = $link->getAttribute(self::TYPE); + // XXX: Am I allowed to do this according to specs? (matching using common_bare_mime) if ($linkRel == $rel && - (is_null($type) || $linkType == $type)) { + (is_null($type) || common_bare_mime($linkType) == common_bare_mime($type))) { return $link->getAttribute(self::HREF); } } From 1ccb934541c490a534027760ffb07da6027d4ddc Mon Sep 17 00:00:00 2001 From: Mikael Nordfeldth Date: Sat, 6 May 2017 12:25:27 +0200 Subject: [PATCH 06/11] Return false immediately if $url is empty for common_valid_http_url --- lib/util.php | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/lib/util.php b/lib/util.php index a177c92a25..62db64d828 100644 --- a/lib/util.php +++ b/lib/util.php @@ -1885,6 +1885,10 @@ function common_log_objstring(&$object) function common_valid_http_url($url, $secure=false) { + if (empty($url)) { + return false; + } + // If $secure is true, only allow https URLs to pass // (if false, we use '?' in 'https?' to say the 's' is optional) $regex = $secure ? '/^https$/' : '/^https?$/'; From d115f9dd1b7082674b91deddfbb25620b94647ea Mon Sep 17 00:00:00 2001 From: Mikael Nordfeldth Date: Sat, 6 May 2017 12:25:50 +0200 Subject: [PATCH 07/11] Output selfLink from notice asActivity[Object] --- classes/Notice.php | 25 +++++++++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) diff --git a/classes/Notice.php b/classes/Notice.php index 3d9968629a..5762de437b 100644 --- a/classes/Notice.php +++ b/classes/Notice.php @@ -315,6 +315,19 @@ class Notice extends Managed_DataObject } } + public function getSelfLink() + { + if ($this->isLocal()) { + return common_local_url('ApiStatusesShow', array('id' => $this->getID(), 'format' => 'atom')); + } + + if (!common_valid_http_url($this->self)) { + throw new InvalidUrlException($this->url); + } + + return $this->self; + } + public function getObjectType($canonical=false) { if (is_null($this->object_type) || $this->object_type==='') { throw new NoObjectTypeException($this); @@ -2064,9 +2077,12 @@ class Notice extends Managed_DataObject } } + try { + $act->selfLink = $this->getSelfLink(); + } catch (InvalidUrlException $e) { + $act->selfLink = null; + } if ($this->isLocal()) { - $act->selfLink = common_local_url('ApiStatusesShow', array('id' => $this->id, - 'format' => 'atom')); $act->editLink = $act->selfLink; } @@ -2164,6 +2180,11 @@ class Notice extends Managed_DataObject $object->title = sprintf('New %1$s by %2$s', ActivityObject::canonicalType($object->type), $this->getProfile()->getNickname()); $object->content = $this->getRendered(); $object->link = $this->getUrl(); + try { + $object->selfLink = $this->getSelfLink(); + } catch (InvalidUrlException $e) { + $object->selfLink = null; + } $object->extra[] = array('status_net', array('notice_id' => $this->id)); From ba4a84602aa24843d17cabaa414674ca9e6a018a Mon Sep 17 00:00:00 2001 From: Mikael Nordfeldth Date: Sat, 6 May 2017 12:38:34 +0200 Subject: [PATCH 08/11] Output proper HTML and XML headers for single Atom entry RFC5023 specifies that the content type parameter 'type=entry' should be used to clarify data. --- lib/apiaction.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/apiaction.php b/lib/apiaction.php index 723e589408..18ec44bb2b 100644 --- a/lib/apiaction.php +++ b/lib/apiaction.php @@ -790,7 +790,8 @@ class ApiAction extends Action function showSingleAtomStatus($notice) { - header('Content-Type: application/atom+xml; charset=utf-8'); + header('Content-Type: application/atom+xml;type=entry;charset="utf-8"'); + print '' . "\n"; print $notice->asAtomEntry(true, true, true, $this->scoped); } From 7767c57087f314f688ea38fce3cbf1d711bfafbc Mon Sep 17 00:00:00 2001 From: Mikael Nordfeldth Date: Sat, 6 May 2017 13:22:10 +0200 Subject: [PATCH 09/11] Notice_prefs now available (I just copied Profile_prefs) --- classes/Notice_prefs.php | 172 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 172 insertions(+) create mode 100644 classes/Notice_prefs.php diff --git a/classes/Notice_prefs.php b/classes/Notice_prefs.php new file mode 100644 index 0000000000..1bbf309da4 --- /dev/null +++ b/classes/Notice_prefs.php @@ -0,0 +1,172 @@ +. + * + * @category Data + * @package GNUsocial + * @author Mikael Nordfeldth + * @copyright 2013 Free Software Foundation, Inc. + * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 + * @link http://www.gnu.org/software/social/ + */ + +class Notice_prefs extends Managed_DataObject +{ + public $__table = 'notice_prefs'; // table name + public $notice_id; // int(4) primary_key not_null + public $namespace; // varchar(191) not_null + public $topic; // varchar(191) not_null + public $data; // text + public $created; // datetime not_null default_0000-00-00%2000%3A00%3A00 + public $modified; // timestamp not_null default_CURRENT_TIMESTAMP + + public static function schemaDef() + { + return array( + 'fields' => array( + 'notice_id' => array('type' => 'int', 'not null' => true, 'description' => 'user'), + 'namespace' => array('type' => 'varchar', 'length' => 191, 'not null' => true, 'description' => 'namespace, like pluginname or category'), + 'topic' => array('type' => 'varchar', 'length' => 191, 'not null' => true, 'description' => 'preference key, i.e. description, age...'), + 'data' => array('type' => 'blob', 'description' => 'topic data, may be anything'), + 'created' => array('type' => 'datetime', 'not null' => true, 'description' => 'date this record was created'), + 'modified' => array('type' => 'timestamp', 'not null' => true, 'description' => 'date this record was modified'), + ), + 'primary key' => array('notice_id', 'namespace', 'topic'), + 'foreign keys' => array( + 'notice_prefs_notice_id_fkey' => array('notice', array('notice_id' => 'id')), + ), + 'indexes' => array( + 'notice_prefs_notice_id_idx' => array('notice_id'), + ), + ); + } + + static function getNamespacePrefs(Notice $notice, $namespace, array $topic=array()) + { + if (empty($topic)) { + $prefs = new Notice_prefs(); + $prefs->notice_id = $notice->getID(); + $prefs->namespace = $namespace; + $prefs->find(); + } else { + $prefs = self::pivotGet('notice_id', $notice->getID(), array('namespace'=>$namespace, 'topic'=>$topic)); + } + + if (empty($prefs->N)) { + throw new NoResultException($prefs); + } + + return $prefs; + } + + static function getNamespace(Notice $notice, $namespace, array $topic=array()) + { + $prefs = self::getNamespacePrefs($notice, $namespace, $topic); + return $prefs->fetchAll(); + } + + static function getAll(Notice $notice) + { + try { + $prefs = self::listFind('notice_id', array($notice->getID())); + } catch (NoResultException $e) { + return array(); + } + + $list = array(); + while ($prefs->fetch()) { + if (!isset($list[$prefs->namespace])) { + $list[$prefs->namespace] = array(); + } + $list[$prefs->namespace][$prefs->topic] = $prefs->data; + } + return $list; + } + + static function getTopic(Notice $notice, $namespace, $topic) { + return self::getByPK(array('notice_id' => $notice->getID(), + 'namespace' => $namespace, + 'topic' => $topic)); + } + + static function getData(Notice $notice, $namespace, $topic, $def=null) { + try { + $pref = self::getTopic($notice, $namespace, $topic); + } catch (NoResultException $e) { + if ($def === null) { + // If no default value was set, continue the exception. + throw $e; + } + // If there was a default value, return that. + return $def; + } + return $pref->data; + } + + static function getConfigData(Notice $notice, $namespace, $topic) { + try { + $data = self::getData($notice, $namespace, $topic); + } catch (NoResultException $e) { + $data = common_config($namespace, $topic); + } + return $data; + } + + /* + * Sets a notice preference based on Notice, namespace and topic + * + * @param Notice $notice Which notice this is for + * @param string $namespace Under which namespace (pluginname etc.) + * @param string $topic Preference name (think key in key-val store) + * @param string $data Data to be put into preference storage, null means delete + * + * @return true if changes are made, false if no action taken + * @throws ServerException if preference could not be saved + */ + static function setData(Notice $notice, $namespace, $topic, $data=null) { + try { + $pref = self::getTopic($notice, $namespace, $topic); + if (is_null($data)) { + $pref->delete(); + } else { + $orig = clone($pref); + $pref->data = $data; + $pref->update($orig); + } + return true; + } catch (NoResultException $e) { + if (is_null($data)) { + return false; // No action taken + } + } + + $pref = new Notice_prefs(); + $pref->notice_id = $notice->getID(); + $pref->namespace = $namespace; + $pref->topic = $topic; + $pref->data = $data; + $pref->created = common_sql_now(); + + if ($pref->insert() === false) { + throw new ServerException('Could not save notice preference.'); + } + return true; + } +} From 966971bd12011c2e6c926f2831313ca4762dde34 Mon Sep 17 00:00:00 2001 From: Mikael Nordfeldth Date: Sat, 6 May 2017 13:24:11 +0200 Subject: [PATCH 10/11] Revert some of 8a4bec811b07a0ed9d76d0aceb03855c91a67242 use Notice_prefs instead of adding a new field. The rationale here is simply that the Notice table was _huge_ and I rant into issues with /tmp filling up when altering the tables. So let's just create a new table instead. --- classes/Notice.php | 47 +++++++++++++++++++++++++++++++++++----------- 1 file changed, 36 insertions(+), 11 deletions(-) diff --git a/classes/Notice.php b/classes/Notice.php index 5762de437b..1a7964fc06 100644 --- a/classes/Notice.php +++ b/classes/Notice.php @@ -59,7 +59,6 @@ class Notice extends Managed_DataObject public $content; // text public $rendered; // text public $url; // varchar(191) not 255 because utf8mb4 takes more space - public $self; // varchar(191) not 255 because utf8mb4 takes more space public $created; // datetime multiple_key not_null default_0000-00-00%2000%3A00%3A00 public $modified; // timestamp not_null default_CURRENT_TIMESTAMP public $reply_to; // int(4) @@ -84,7 +83,6 @@ class Notice extends Managed_DataObject 'content' => array('type' => 'text', 'description' => 'update content', 'collate' => 'utf8mb4_general_ci'), 'rendered' => array('type' => 'text', 'description' => 'HTML version of the content'), 'url' => array('type' => 'varchar', 'length' => 191, 'description' => 'URL of any attachment (image, video, bookmark, whatever)'), - 'self' => array('type' => 'varchar', 'length' => 191, 'description' => 'Resolvable URL to the (remote) Atom entry representation'), 'created' => array('type' => 'datetime', 'not null' => true, 'description' => 'date this record was created'), 'modified' => array('type' => 'timestamp', 'not null' => true, 'description' => 'date this record was modified'), 'reply_to' => array('type' => 'int', 'description' => 'notice replied to (usually a guess)'), @@ -321,11 +319,13 @@ class Notice extends Managed_DataObject return common_local_url('ApiStatusesShow', array('id' => $this->getID(), 'format' => 'atom')); } - if (!common_valid_http_url($this->self)) { - throw new InvalidUrlException($this->url); + $selfLink = $this->getPref('ostatus', 'self'); + + if (!common_valid_http_url($selfLink)) { + throw new InvalidUrlException($selfLink); } - return $this->self; + return $selfLink; } public function getObjectType($canonical=false) { @@ -555,9 +555,6 @@ class Notice extends Managed_DataObject $notice->source = $source; $notice->uri = $uri; $notice->url = $url; - if ($self && common_valid_http_url($self)) { - $notice->self = $self; - } // Get the groups here so we can figure out replies and such if (!isset($groups)) { @@ -736,6 +733,10 @@ class Notice extends Managed_DataObject } } + if ($self && common_valid_http_url($self)) { + $notice->setPref('ostatus', 'self', $self); + } + // Only save 'attention' and metadata stuff (URLs, tags...) stuff if // the activityverb is a POST (since stuff like repeat, favorite etc. // reasonably handle notifications themselves. @@ -873,9 +874,6 @@ class Notice extends Managed_DataObject $stored->source = $source; $stored->uri = $uri; $stored->url = $url; - if (common_valid_http_url($stored->self)) { - $stored->self = $self; - } $stored->verb = $act->verb; $content = $act->content ?: $act->summary; @@ -1028,6 +1026,10 @@ class Notice extends Managed_DataObject throw new ServerException('StartNoticeSave did not give back a Notice'); } + if ($self && common_valid_http_url($self)) { + $stored->setPref('ostatus', 'self', $self); + } + // Only save 'attention' and metadata stuff (URLs, tags...) stuff if // the activityverb is a POST (since stuff like repeat, favorite etc. // reasonably handle notifications themselves. @@ -3119,4 +3121,27 @@ class Notice extends Managed_DataObject } print "\n"; } + + public function delPref($namespace, $topic) { + return Notice_prefs::setData($this, $namespace, $topic, null); + } + + public function getPref($namespace, $topic, $default=null) { + // If you want an exception to be thrown, call Notice_prefs::getData directly + try { + return Notice_prefs::getData($this, $namespace, $topic, $default); + } catch (NoResultException $e) { + return null; + } + } + + // The same as getPref but will fall back to common_config value for the same namespace/topic + public function getConfigPref($namespace, $topic) + { + return Notice_prefs::getConfigData($this, $namespace, $topic); + } + + public function setPref($namespace, $topic, $data) { + return Notice_prefs::setData($this, $namespace, $topic, $data); + } } From 5ad2f2873eba2694e79cf7e09728d456afad270f Mon Sep 17 00:00:00 2001 From: Mikael Nordfeldth Date: Sat, 6 May 2017 13:54:42 +0200 Subject: [PATCH 11/11] ...and make sure we checkschema on Notice_prefs on upgrade... --- db/core.php | 1 + 1 file changed, 1 insertion(+) diff --git a/db/core.php b/db/core.php index f654d79d99..56213eb338 100644 --- a/db/core.php +++ b/db/core.php @@ -41,6 +41,7 @@ $classes = array('Schema_version', 'Notice', 'Notice_location', 'Notice_source', + 'Notice_prefs', 'Reply', 'Consumer', 'Token',