]> git.mxchange.org Git - quix0rs-gnu-social.git/blobdiff - classes/Notice.php
No more needed (for this fix) but maybe later. So I always only comment them out.
[quix0rs-gnu-social.git] / classes / Notice.php
index 37765ce38c533bda143256b840820261d13acf5c..263cc4e32394ecbcd2880ac2f8cc91e3067a9779 100644 (file)
@@ -276,19 +276,21 @@ class Notice extends Managed_DataObject
 
     /*
      * Get the original representation URL of this notice.
+     *
+     * @param boolean $fallback     Whether to fall back to generate a local URL or throw InvalidUrlException
      */
-    public function getUrl()
+    public function getUrl($fallback=false)
     {
         // The risk is we start having empty urls and non-http uris...
         // and we can't really handle any other protocol right now.
         switch (true) {
         case common_valid_http_url($this->url): // should we allow non-http/https URLs?
             return $this->url;
-        case $this->isLocal():
+        case !$this->isLocal() && common_valid_http_url($this->uri): // Sometimes we only have the URI for remote posts.
+            return $this->uri;
+        case $this->isLocal() || $fallback:
             // let's generate a valid link to our locally available notice on demand
             return common_local_url('shownotice', array('notice' => $this->id), null, null, false);
-        case common_valid_http_url($this->uri):
-            return $this->uri;
         default:
             common_debug('No URL available for notice: id='.$this->id);
             throw new InvalidUrlException($this->url);
@@ -414,7 +416,7 @@ class Notice extends Managed_DataObject
      * @return Notice
      * @throws ClientException
      */
-    static function saveNew($profile_id, $content, $source, array $options=null) {
+    static function saveNew($profile_id, $content, $source, array $options=array()) {
         $defaults = array('uri' => null,
                           'url' => null,
                           'conversation' => null,   // URI of conversation
@@ -425,13 +427,16 @@ class Notice extends Managed_DataObject
                           'object_type' => null,
                           'verb' => null);
 
-        if (!empty($options) && is_array($options)) {
+        /*
+         * Above type-hint is already array, so simply count it, this saves
+         * "some" CPU cycles.
+         */
+        if (count($options) > 0) {
             $options = array_merge($defaults, $options);
-            extract($options);
-        } else {
-            extract($defaults);
         }
 
+        extract($options);
+
         if (!isset($is_local)) {
             $is_local = Notice::LOCAL_PUBLIC;
         }
@@ -537,8 +542,7 @@ class Notice extends Managed_DataObject
                 throw new ClientException(_('You cannot repeat your own notice.'));
             }
 
-            if ($repeat->scope != Notice::SITE_SCOPE &&
-                $repeat->scope != Notice::PUBLIC_SCOPE) {
+            if ($repeat->isPrivateScope()) {
                 // TRANS: Client error displayed when trying to repeat a non-public notice.
                 throw new ClientException(_('Cannot repeat a private notice.'), 403);
             }
@@ -995,6 +999,7 @@ class Notice extends Managed_DataObject
 
         if ($this->isPublic()) {
             $this->blowStream('public');
+            $this->blowStream('networkpublic');
         }
 
         self::blow('notice:list-ids:conversation:%s', $this->conversation);
@@ -1039,6 +1044,7 @@ class Notice extends Managed_DataObject
 
         if ($this->isPublic()) {
             self::blow('public;last');
+            self::blow('networkpublic;last');
         }
 
         self::blow('fave:by_notice', $this->id);
@@ -1111,7 +1117,7 @@ class Notice extends Managed_DataObject
      *
      * @return void
      */
-    function saveKnownUrls($urls)
+    function saveKnownUrls(array $urls)
     {
         if (common_config('attachments', 'process_links')) {
             // @fixme validation?
@@ -1489,7 +1495,7 @@ class Notice extends Managed_DataObject
         foreach (array_unique($group_ids) as $id) {
             $group = User_group::getKV('id', $id);
             if ($group instanceof User_group) {
-                common_log(LOG_ERR, "Local delivery to group id $id, $group->nickname");
+                common_log(LOG_DEBUG, "Local delivery to group id $id, $group->nickname");
                 $result = $this->addToGroupInbox($group);
                 if (!$result) {
                     common_log_db_error($gi, 'INSERT', __FILE__);
@@ -1685,12 +1691,12 @@ class Notice extends Managed_DataObject
             $ids[] = $reply->profile_id;
         }
 
-        $this->_replies[$this->id] = $ids;
+        $this->_setReplies($ids);
 
         return $ids;
     }
 
-    function _setReplies($replies)
+    function _setReplies(array $replies)
     {
         $this->_replies[$this->id] = $replies;
     }
@@ -1768,13 +1774,11 @@ class Notice extends Managed_DataObject
                }
                
                $groups = User_group::multiGet('id', $ids);
-               
-               $this->_groups[$this->id] = $groups->fetchAll();
-               
+               $this->_setGroups($groups->fetchAll());
                return $this->_groups[$this->id];
     }
-    
-    function _setGroups($groups)
+
+    function _setGroups(array $groups)
     {
         $this->_groups[$this->id] = $groups;
     }
@@ -2499,6 +2503,37 @@ class Notice extends Managed_DataObject
      */
     public function getTags()
     {
+        // Check default scope (non-private notices)
+        $inScope = (!$this->isPrivateScope());
+
+        // Get current profile
+        $profile = Profile::current();
+
+        // Is the general scope check okay and the user in logged in?
+        //* NOISY-DEBUG: */ common_debug('[' . __METHOD__ . ':' . __LINE__ . ']: inScope=' . intval($inScope) . ',profile[]=' . gettype($profile));
+        if (($inScope === TRUE) && ($profile instanceof Profile)) {
+            /*
+             * Check scope, else a privacy leaks happens this way:
+             *
+             * 1) Bob and Alice follow each other and write private notices
+             *    (this->scope=2) to each other.
+             * 2) Bob uses tags in his private notice to alice (which she can
+             *    read from him).
+             * 3) Alice adds that notice (with tags) to her favorites
+             *    ("faving") it.
+             * 4) The tags from Bob's private notice becomes visible in Alice's
+             *    profile.
+             *
+             * This has the simple background that the scope is not being
+             * re-checked. This has to be done here at this point because given
+             * above scenario is a privacy leak as the tags may be *really*
+             * private (nobody else shall see them) such as initmate words or
+             * very political words.
+             */
+            $inScope = $this->inScope($profile);
+            //* NOISY-DEBUG: */ common_debug('[' . __METHOD__ . ':' . __LINE__ . ']: inScope=' . intval($inScope) . ' - After inScope() has been called.');
+        }
+
         $tags = array();
 
         $keypart = sprintf('notice:tags:%d', $this->id);
@@ -2510,7 +2545,9 @@ class Notice extends Managed_DataObject
         } else {
             $tag = new Notice_tag();
             $tag->notice_id = $this->id;
-            if ($tag->find()) {
+
+            // Check scope for privacy-leak protection (see some lines above why)
+            if (($inScope === TRUE) && ($tag->find())) {
                 while ($tag->fetch()) {
                     $tags[] = $tag->tag;
                 }
@@ -2634,12 +2671,8 @@ class Notice extends Managed_DataObject
 
     function isPublic()
     {
-        if (common_config('public', 'localonly')) {
-            return ($this->is_local == Notice::LOCAL_PUBLIC);
-        } else {
-            return (($this->is_local != Notice::LOCAL_NONPUBLIC) &&
-                    ($this->is_local != Notice::GATEWAY));
-        }
+        return (($this->is_local != Notice::LOCAL_NONPUBLIC) &&
+                ($this->is_local != Notice::GATEWAY));
     }
 
     /**
@@ -2656,7 +2689,7 @@ class Notice extends Managed_DataObject
      *
      * @return boolean whether the profile is in the notice's scope
      */
-    function inScope($profile)
+    function inScope(Profile $profile=null)
     {
         if (is_null($profile)) {
             $keypart = sprintf('notice:in-scope-for:%d:null', $this->id);
@@ -2679,7 +2712,7 @@ class Notice extends Managed_DataObject
         return ($result == 1) ? true : false;
     }
 
-    protected function _inScope($profile)
+    protected function _inScope(Profile $profile=null)
     {
         if (!is_null($this->scope)) {
             $scope = $this->scope;
@@ -2719,7 +2752,7 @@ class Notice extends Managed_DataObject
 
                 $reply = Reply::pkeyGet(array('notice_id' => $this->id,
                                              'profile_id' => $profile->id));
-                                                                                
+
                 if (!$reply instanceof Reply) {
                     return false;
                 }
@@ -2768,8 +2801,8 @@ class Notice extends Managed_DataObject
         }
     }
 
-    function isHiddenSpam($profile) {
-        
+    function isHiddenSpam(Profile $profile=null) {
+
         // Hide posts by silenced users from everyone but moderators.
 
         if (common_config('notice', 'hidespam')) {
@@ -2833,7 +2866,7 @@ class Notice extends Managed_DataObject
        return $scope;
     }
 
-       static function fillProfiles($notices)
+       static function fillProfiles(array $notices)
        {
                $map = self::getProfiles($notices);
                
@@ -2850,8 +2883,8 @@ class Notice extends Managed_DataObject
                
                return array_values($map);
        }
-       
-       static function getProfiles(&$notices)
+
+       static function getProfiles(array &$notices)
        {
                $ids = array();
                foreach ($notices as $notice) {
@@ -2862,8 +2895,8 @@ class Notice extends Managed_DataObject
                
                return Profile::pivotGet('id', $ids); 
        }
-       
-       static function fillGroups(&$notices)
+
+       static function fillGroups(array &$notices)
        {
         $ids = self::_idsOf($notices);
                
@@ -2903,7 +2936,7 @@ class Notice extends Managed_DataObject
                return array_keys($ids);
     }
 
-    static function fillAttachments(&$notices)
+    static function fillAttachments(array &$notices)
     {
         $ids = self::_idsOf($notices);
 
@@ -2932,7 +2965,7 @@ class Notice extends Managed_DataObject
                }
     }
 
-    static function fillReplies(&$notices)
+    static function fillReplies(array &$notices)
     {
         $ids = self::_idsOf($notices);
         $replyMap = Reply::listGet('notice_id', $ids);
@@ -2954,22 +2987,33 @@ class Notice extends Managed_DataObject
             return $this->_repeats[$this->id];
         }
         $repeatMap = Notice::listGet('repeat_of', array($this->id));
-        $this->_repeats[$this->id] = $repeatMap[$this->id];
+        $this->_setRepeats($repeatMap[$this->id]);
         return $this->_repeats[$this->id];
     }
 
-    function _setRepeats($repeats)
+    function _setRepeats(array $repeats)
     {
         $this->_repeats[$this->id] = $repeats;
     }
 
-    static function fillRepeats(&$notices)
+    static function fillRepeats(array &$notices)
     {
         $ids = self::_idsOf($notices);
         $repeatMap = Notice::listGet('repeat_of', $ids);
         foreach ($notices as $notice) {
-               $repeats = $repeatMap[$notice->id];
+            $repeats = $repeatMap[$notice->id];
             $notice->_setRepeats($repeats);
         }
     }
+
+    /**
+     * Checks whether this notice is in "private scope" (non-public notice)
+     *
+     * @return $isPrivate Whether this notice is private
+     */
+    public function isPrivateScope ()
+    {
+        return ($this->scope != Notice::SITE_SCOPE &&
+                $this->scope != Notice::PUBLIC_SCOPE);
+    }
 }