]> git.mxchange.org Git - friendica.git/blobdiff - include/items.php
track whether contact is a community page or not
[friendica.git] / include / items.php
index ba95919a6ba9672a846b2bfa3fdf2c7d4c18caec..68acb45f9b6fc7bbf86183316421dd3587b2bf3d 100755 (executable)
@@ -308,7 +308,7 @@ function get_atom_elements($feed,$item) {
        if($rawauthor && $rawauthor[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['link']) {
                $base = $rawauthor[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['link'];
                foreach($base as $link) {
-                       if(! $res['author-avatar']) {
+                       if(!x($res, 'author-avatar') || !$res['author-avatar']) {
                                if($link['attribs']['']['rel'] === 'photo' || $link['attribs']['']['rel'] === 'avatar')
                                        $res['author-avatar'] = unxmlify($link['attribs']['']['href']);
                        }
@@ -323,7 +323,7 @@ function get_atom_elements($feed,$item) {
                        foreach($base as $link) {
                                if($link['attribs']['']['rel'] === 'alternate' && (! $res['author-link']))
                                        $res['author-link'] = unxmlify($link['attribs']['']['href']);
-                               if(! $res['author-avatar']) {
+                               if(!x($res, 'author-avatar') || !$res['author-avatar']) {
                                        if($link['attribs']['']['rel'] === 'avatar' || $link['attribs']['']['rel'] === 'photo')
                                                $res['author-avatar'] = unxmlify($link['attribs']['']['href']);
                                }
@@ -503,7 +503,7 @@ function get_atom_elements($feed,$item) {
                $base = $rawowner[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['link'];
 
                foreach($base as $link) {
-                       if(! $res['owner-avatar']) {
+                       if(!x($res, 'owner-avatar') || !$res['owner-avatar']) {
                                if($link['attribs']['']['rel'] === 'photo' || $link['attribs']['']['rel'] === 'avatar')                 
                                        $res['owner-avatar'] = unxmlify($link['attribs']['']['href']);
                        }
@@ -682,7 +682,7 @@ function item_store($arr,$force_parent = false) {
                unset($arr['dsprsig']);
        }
 
-       if($arr['gravity'])
+       if(x($arr, 'gravity'))
                $arr['gravity'] = intval($arr['gravity']);
        elseif($arr['parent-uri'] === $arr['uri'])
                $arr['gravity'] = 0;
@@ -742,6 +742,7 @@ function item_store($arr,$force_parent = false) {
 
        if($arr['parent-uri'] === $arr['uri']) {
                $parent_id = 0;
+               $parent_deleted = 0;
                $allow_cid = $arr['allow_cid'];
                $allow_gid = $arr['allow_gid'];
                $deny_cid  = $arr['deny_cid'];
@@ -800,6 +801,8 @@ function item_store($arr,$force_parent = false) {
                                logger('item_store: item parent was not found - ignoring item');
                                return 0;
                        }
+                       
+                       $parent_deleted = 0;
                }
        }
 
@@ -905,7 +908,7 @@ function item_store($arr,$force_parent = false) {
                );
        }
 
-       tgroup_deliver($arr['uid'],$current_post);
+       tag_deliver($arr['uid'],$current_post);
 
        return $current_post;
 }
@@ -923,22 +926,22 @@ function get_item_contact($item,$contacts) {
 }
 
 
-function tgroup_deliver($uid,$item_id) {
-
+function tag_deliver($uid,$item_id) {
 
-       // setup a second delivery chain for forum/community posts if appropriate
+       // look for mention tags and setup a second delivery chain for forum/community posts if appropriate
 
        $a = get_app();
 
-       $deliver_to_tgroup = false;
+       $mention = false;
 
-       $u = q("select * from user where uid = %d and `page-flags` = %d limit 1",
-               intval($uid),
-               intval(PAGE_COMMUNITY)
+       $u = q("select uid, nickname, language, username, email, `page-flags`, `notify-flags` from user where uid = %d limit 1",
+               intval($uid)
        );
        if(! count($u))
                return;
 
+       $community_page = (($u[0]['page-flags'] == PAGE_COMMUNITY) ? true : false);
+
        $i = q("select * from item where id = %d and uid = %d limit 1",
                intval($item_id),
                intval($uid)
@@ -948,13 +951,6 @@ function tgroup_deliver($uid,$item_id) {
 
        $item = $i[0];
 
-       // prevent delivery looping - only proceed
-       // if the message originated elsewhere and is a top-level post
-
-       if(($item['wall']) || ($item['origin']) || ($item['id'] != $item['parent']))
-               return;
-
-
        $link = normalise_link($a->get_baseurl() . '/profile/' . $u[0]['nickname']);
 
        // Diaspora uses their own hardwired link URL in @-tags
@@ -966,19 +962,57 @@ function tgroup_deliver($uid,$item_id) {
        if($cnt) {
                foreach($matches as $mtch) {
                        if(link_compare($link,$mtch[1]) || link_compare($dlink,$mtch[1])) {
-                               $deliver_to_tgroup = true;
-                               logger('tgroup_deliver: local group mention found: ' . $mtch[2]);
+                               $mention = true;
+                               logger('tag_deliver: mention found: ' . $mtch[2]);
                        }
                }
        }
 
-       if(! $deliver_to_tgroup)
+       if(! $mention)
+               return;
+
+       // send a notification
+
+       require_once('include/enotify.php');
+       notification(array(
+               'type'         => NOTIFY_TAGSELF,
+               'notify_flags' => $u[0]['notify-flags'],
+               'language'     => $u[0]['language'],
+               'to_name'      => $u[0]['username'],
+               'to_email'     => $u[0]['email'],
+               'uid'          => $u[0]['uid'],
+               'item'         => $item,
+               'link'         => $a->get_baseurl() . '/display/' . $u[0]['nickname'] . '/' . $item['id'],
+               'source_name'  => $item['author-name'],
+               'source_link'  => $item['author-link'],
+               'source_photo' => $item['author-avatar'],
+               'verb'         => ACTIVITY_TAG,
+               'otype'        => 'item'
+       ));
+
+       if(! $community_page)
+               return;
+
+       // tgroup delivery - setup a second delivery chain
+       // prevent delivery looping - only proceed
+       // if the message originated elsewhere and is a top-level post
+
+       if(($item['wall']) || ($item['origin']) || ($item['id'] != $item['parent']))
                return;
 
        // now change this copy of the post to a forum head message and deliver to all the tgroup members
 
 
-       q("update item set wall = 1, origin = 1, forum_mode = 1 where id = %d limit 1",
+       $c = q("select name, url, thumb from contact where self = 1 and uid = %d limit 1",
+               intval($u[0]['uid'])
+       );
+       if(! count($c))
+               return;
+
+       q("update item set wall = 1, origin = 1, forum_mode = 1, `owner-name` = '%s', `owner-link` = '%s', `owner-avatar` = '%s'  where id = %d limit 1",
+               dbesc($c[0]['name']),
+               dbesc($c[0]['url']),
+               dbesc($c[0]['thumb']),
                intval($item_id)
        );
 
@@ -995,8 +1029,8 @@ function dfrn_deliver($owner,$contact,$atom, $dissolve = false) {
 
        $a = get_app();
 
-       if((! strlen($contact['issued-id'])) && (! $contact['duplex']) && (! ($owner['page-flags'] == PAGE_COMMUNITY)))
-               return 3;
+//     if((! strlen($contact['issued-id'])) && (! $contact['duplex']) && (! ($owner['page-flags'] == PAGE_COMMUNITY)))
+//             return 3;
 
        $idtosend = $orig_id = (($contact['dfrn-id']) ? $contact['dfrn-id'] : $contact['issued-id']);
 
@@ -1012,6 +1046,22 @@ function dfrn_deliver($owner,$contact,$atom, $dissolve = false) {
        if(! $rino_enable)
                $rino = 0;
 
+       $ssl_val = intval(get_config('system','ssl_policy'));
+       $ssl_policy = '';
+
+       switch($ssl_val){
+               case SSL_POLICY_FULL:
+                       $ssl_policy = 'full';
+                       break;
+               case SSL_POLICY_SELFSIGN:
+                       $ssl_policy = 'self';
+                       break;                  
+               case SSL_POLICY_NONE:
+               default:
+                       $ssl_policy = 'none';
+                       break;
+       }
+
        $url = $contact['notify'] . '&dfrn_id=' . $idtosend . '&dfrn_version=' . DFRN_PROTOCOL_VERSION . (($rino) ? '&rino=1' : '');
 
        logger('dfrn_deliver: ' . $url);
@@ -1043,11 +1093,14 @@ function dfrn_deliver($owner,$contact,$atom, $dissolve = false) {
        $challenge    = hex2bin((string) $res->challenge);
        $dfrn_version = (float) (($res->dfrn_version) ? $res->dfrn_version : 2.0);
        $rino_allowed = ((intval($res->rino) === 1) ? 1 : 0);
+       $page         = (($owner['page-flags'] == PAGE_COMMUNITY) ? 1 : 0);
 
        $final_dfrn_id = '';
 
 
-       if(($contact['duplex'] && strlen($contact['pubkey'])) || ($owner['page-flags'] == PAGE_COMMUNITY)) {
+       if(($contact['duplex'] && strlen($contact['pubkey'])) 
+               || ($owner['page-flags'] == PAGE_COMMUNITY && strlen($contact['pubkey']))
+               || ($contact['rel'] == CONTACT_IS_SHARING && strlen($contact['pubkey']))) {
                openssl_public_decrypt($sent_dfrn_id,$final_dfrn_id,$contact['pubkey']);
                openssl_public_decrypt($challenge,$postvars['challenge'],$contact['pubkey']);
        }
@@ -1082,6 +1135,11 @@ function dfrn_deliver($owner,$contact,$atom, $dissolve = false) {
                $postvars['perm'] = 'r';
        }
 
+       $postvars['ssl_policy'] = $ssl_policy;
+
+       if($page)
+               $postvars['page'] = '1';
+       
        if($rino && $rino_allowed && (! $dissolve)) {
                $key = substr(random_string(),0,16);
                $data = bin2hex(aes_encrypt($postvars['data'],$key));
@@ -1090,7 +1148,10 @@ function dfrn_deliver($owner,$contact,$atom, $dissolve = false) {
 
 
                if($dfrn_version >= 2.1) {      
-                       if(($contact['duplex'] && strlen($contact['pubkey'])) || ($owner['page-flags'] == PAGE_COMMUNITY)) {
+                       if(($contact['duplex'] && strlen($contact['pubkey'])) 
+                               || ($owner['page-flags'] == PAGE_COMMUNITY && strlen($contact['pubkey']))
+                               || ($contact['rel'] == CONTACT_IS_SHARING && strlen($contact['pubkey']))) {
+
                                openssl_public_encrypt($key,$postvars['key'],$contact['pubkey']);
                        }
                        else {
@@ -1272,12 +1333,28 @@ function consume_feed($xml,$importer,&$contact, &$hub, $datedir = 0, $pass = 0)
        }
 
        if((is_array($contact)) && ($name_updated) && (strlen($new_name)) && ($name_updated > $contact['name-date'])) {
-               q("UPDATE `contact` SET `name` = '%s', `name-date` = '%s' WHERE `uid` = %d AND `id` = %d LIMIT 1",
+               $r = q("select * from contact where uid = %d and id = %d limit 1",
+                       intval($contact['uid']),
+                       intval($contact['id'])
+               );
+
+               $x = q("UPDATE `contact` SET `name` = '%s', `name-date` = '%s' WHERE `uid` = %d AND `id` = %d LIMIT 1",
                        dbesc(notags(trim($new_name))),
                        dbesc(datetime_convert()),
                        intval($contact['uid']),
                        intval($contact['id'])
                );
+
+               // do our best to update the name on content items
+
+               if(count($r)) {
+                       q("update item set `author-name` = '%s' where `author-name` = '%s' and `author-link` = '%s' and uid = %d",
+                               dbesc(notags(trim($new_name))),
+                               dbesc($r[0]['name']),
+                               dbesc($r[0]['url']),
+                               intval($contact['uid'])
+                       );
+               }
        }
 
        if(strlen($birthday)) {
@@ -1469,13 +1546,18 @@ function consume_feed($xml,$importer,&$contact, &$hub, $datedir = 0, $pass = 0)
                                $item_id  = $item->get_id();
                                $datarray = get_atom_elements($feed,$item);
 
-                               if(! x($datarray,'author-name'))
+
+                               if((! x($datarray,'author-name')) && ($contact['network'] != NETWORK_DFRN))
                                        $datarray['author-name'] = $contact['name'];
-                               if(! x($datarray,'author-link'))
+                               if((! x($datarray,'author-link')) && ($contact['network'] != NETWORK_DFRN))
                                        $datarray['author-link'] = $contact['url'];
-                               if(! x($datarray,'author-avatar'))
+                               if((! x($datarray,'author-avatar')) && ($contact['network'] != NETWORK_DFRN))
                                        $datarray['author-avatar'] = $contact['thumb'];
 
+                               if((! x($datarray,'author-name')) || (! x($datarray,'author-link'))) {
+                                       logger('consume_feed: no author information! ' . print_r($datarray,true));
+                                       continue;
+                               }
 
                                $r = q("SELECT `uid`, `last-child`, `edited`, `body` FROM `item` WHERE `uri` = '%s' AND `uid` = %d LIMIT 1",
                                        dbesc($item_id),
@@ -1486,7 +1568,8 @@ function consume_feed($xml,$importer,&$contact, &$hub, $datedir = 0, $pass = 0)
 
                                if(count($r)) {
                                        if((x($datarray,'edited') !== false) && (datetime_convert('UTC','UTC',$datarray['edited']) !== $r[0]['edited'])) {  
-                                               $r = q("UPDATE `item` SET `body` = '%s', `edited` = '%s' WHERE `uri` = '%s' AND `uid` = %d LIMIT 1",
+                                               $r = q("UPDATE `item` SET `title` = '%s', `body` = '%s', `edited` = '%s' WHERE `uri` = '%s' AND `uid` = %d LIMIT 1",
+                                                       dbesc($datarray['title']),
                                                        dbesc($datarray['body']),
                                                        dbesc(datetime_convert('UTC','UTC',$datarray['edited'])),
                                                        dbesc($item_id),
@@ -1514,8 +1597,9 @@ function consume_feed($xml,$importer,&$contact, &$hub, $datedir = 0, $pass = 0)
                                }
 
                                $force_parent = false;
-                               if($contact['network'] === NETWORK_OSTATUS) {
-                                       $force_parent = true;
+                               if($contact['network'] === NETWORK_OSTATUS || stristr($contact['url'],'twitter.com')) {
+                                       if($contact['network'] === NETWORK_OSTATUS)
+                                               $force_parent = true;
                                        if(strlen($datarray['title']))
                                                unset($datarray['title']);
                                        $r = q("UPDATE `item` SET `last-child` = 0, `changed` = '%s' WHERE `parent-uri` = '%s' AND `uid` = %d",
@@ -1536,6 +1620,14 @@ function consume_feed($xml,$importer,&$contact, &$hub, $datedir = 0, $pass = 0)
                                if((activity_match($datarray['verb'],ACTIVITY_LIKE)) || (activity_match($datarray['verb'],ACTIVITY_DISLIKE))) {
                                        $datarray['type'] = 'activity';
                                        $datarray['gravity'] = GRAVITY_LIKE;
+                                       // only one like or dislike per person
+                                       $r = q("select id from item where uid = %d and `contact-id` = %d and verb ='%s' and deleted = 0 limit 1",
+                                               intval($datarray['uid']),
+                                               intval($datarray['contact-id']),
+                                               dbesc($datarray['verb'])
+                                       );
+                                       if($r && count($r))
+                                               continue; 
                                }
 
                                if(($datarray['verb'] === ACTIVITY_TAG) && ($datarray['object-type'] === ACTIVITY_OBJ_TAGTERM)) {
@@ -1576,14 +1668,19 @@ function consume_feed($xml,$importer,&$contact, &$hub, $datedir = 0, $pass = 0)
                                $datarray = get_atom_elements($feed,$item);
 
                                if(is_array($contact)) {
-                                       if(! x($datarray,'author-name'))
+                                       if((! x($datarray,'author-name')) && ($contact['network'] != NETWORK_DFRN))
                                                $datarray['author-name'] = $contact['name'];
-                                       if(! x($datarray,'author-link'))
+                                       if((! x($datarray,'author-link')) && ($contact['network'] != NETWORK_DFRN))
                                                $datarray['author-link'] = $contact['url'];
-                                       if(! x($datarray,'author-avatar'))
+                                       if((! x($datarray,'author-avatar')) && ($contact['network'] != NETWORK_DFRN))
                                                $datarray['author-avatar'] = $contact['thumb'];
                                }
 
+                               if((! x($datarray,'author-name')) || (! x($datarray,'author-link'))) {
+                                       logger('consume_feed: no author information! ' . print_r($datarray,true));
+                                       continue;
+                               }
+
                                // special handling for events
 
                                if((x($datarray,'object-type')) && ($datarray['object-type'] === ACTIVITY_OBJ_EVENT)) {
@@ -1616,7 +1713,8 @@ function consume_feed($xml,$importer,&$contact, &$hub, $datedir = 0, $pass = 0)
 
                                if(count($r)) {
                                        if((x($datarray,'edited') !== false) && (datetime_convert('UTC','UTC',$datarray['edited']) !== $r[0]['edited'])) {  
-                                               $r = q("UPDATE `item` SET `body` = '%s', `edited` = '%s' WHERE `uri` = '%s' AND `uid` = %d LIMIT 1",
+                                               $r = q("UPDATE `item` SET `title` = '%s', `body` = '%s', `edited` = '%s' WHERE `uri` = '%s' AND `uid` = %d LIMIT 1",
+                                                       dbesc($datarray['title']),
                                                        dbesc($datarray['body']),
                                                        dbesc(datetime_convert('UTC','UTC',$datarray['edited'])),
                                                        dbesc($item_id),
@@ -1662,7 +1760,7 @@ function consume_feed($xml,$importer,&$contact, &$hub, $datedir = 0, $pass = 0)
                                if(! is_array($contact))
                                        return;
 
-                               if($contact['network'] === NETWORK_OSTATUS || stristr($permalink,'twitter.com')) {
+                               if($contact['network'] === NETWORK_OSTATUS || stristr($contact['url'],'twitter.com')) {
                                        if(strlen($datarray['title']))
                                                unset($datarray['title']);
                                        $datarray['last-child'] = 1;
@@ -1682,6 +1780,18 @@ function consume_feed($xml,$importer,&$contact, &$hub, $datedir = 0, $pass = 0)
                                $datarray['parent-uri'] = $item_id;
                                $datarray['uid'] = $importer['uid'];
                                $datarray['contact-id'] = $contact['id'];
+
+                               if(! link_compare($datarray['owner-link'],$contact['url'])) {
+                                       // The item owner info is not our contact. It's OK and is to be expected if this is a tgroup delivery, 
+                                       // but otherwise there's a possible data mixup on the sender's system.
+                                       // the tgroup delivery code called from item_store will correct it if it's a forum,
+                                       // but we're going to unconditionally correct it here so that the post will always be owned by our contact. 
+                                       logger('local_delivery: Correcting item owner.', LOGGER_DEBUG);
+                                       $datarray['owner-name']   = $contact['name'];
+                                       $datarray['owner-link']   = $contact['url'];
+                                       $datarray['owner-avatar'] = $contact['thumb'];
+                               }
+
                                $r = item_store($datarray);
                                continue;
 
@@ -1811,6 +1921,7 @@ function local_delivery($importer,$data) {
                        'language'     => $importer['language'],
                        'to_name'      => $importer['username'],
                        'to_email'     => $importer['email'],
+                       'uid'          => $importer['importer_uid'],
                        'item'         => $fsugg,
                        'link'         => $a->get_baseurl() . '/notifications/intros',
                        'source_name'  => $importer['name'],
@@ -1862,6 +1973,7 @@ function local_delivery($importer,$data) {
                        'language' => $importer['language'],
                        'to_name' => $importer['username'],
                        'to_email' => $importer['email'],
+                       'uid' => $importer['importer_uid'],
                        'item' => $msg,
                        'source_name' => $msg['from-name'],
                        'source_link' => $importer['url'],
@@ -2000,13 +2112,12 @@ function local_delivery($importer,$data) {
                }
 
                if($is_reply) {
-
                        $community = false;
 
                        if($importer['page-flags'] == PAGE_COMMUNITY) {
                                $sql_extra = '';
                                $community = true;
-                               logger('local_delivery: community reply');
+                               logger('local_delivery: possible community reply');
                        }
                        else
                                $sql_extra = " and contact.self = 1 and item.wall = 1 ";
@@ -2014,7 +2125,9 @@ function local_delivery($importer,$data) {
                        // was the top-level post for this reply written by somebody on this site? 
                        // Specifically, the recipient? 
 
-                       $r = q("select `item`.`id`, `item`.`uri`, `item`.`tag`, 
+                       $is_a_remote_comment = false;
+
+                       $r = q("select `item`.`id`, `item`.`uri`, `item`.`tag`, `item`.`forum_mode`,`item`.`origin`,`item`.`wall`, 
                                `contact`.`name`, `contact`.`url`, `contact`.`thumb` from `item` 
                                LEFT JOIN `contact` ON `contact`.`id` = `item`.`contact-id` 
                                WHERE `item`.`uri` = '%s' AND `item`.`parent-uri` = '%s'
@@ -2025,16 +2138,29 @@ function local_delivery($importer,$data) {
                                dbesc($parent_uri),
                                intval($importer['importer_uid'])
                        );
+                       if($r && count($r))
+                               $is_a_remote_comment = true;                    
+
+                       // Does this have the characteristics of a community comment?
+                       // If it's a reply to a wall post on a community page it's a 
+                       // valid community comment. Also forum_mode makes it valid for sure. 
+                       // If neither, it's not.
+
+                       if($is_a_remote_comment && $community) {
+                               if((! $r[0]['forum_mode']) && (! $r[0]['wall'])) {
+                                       $is_a_remote_comment = false;
+                                       logger('local_delivery: not a community reply');
+                               }
+                       }
 
-                       if($r && count($r)) {   
-
+                       if($is_a_remote_comment) {
                                logger('local_delivery: received remote comment');
                                $is_like = false;
                                // remote reply to our post. Import and then notify everybody else.
                                $datarray = get_atom_elements($feed,$item);
 
 
-               // TODO: make this next part work against both delivery threads of a community post
+                               // TODO: make this next part work against both delivery threads of a community post
 
 //                             if((! link_compare($datarray['author-link'],$importer['url'])) && (! $community)) {
 //                                     logger('local_delivery: received relay claiming to be from ' . $importer['url'] . ' however comment author url is ' . $datarray['author-link'] ); 
@@ -2055,6 +2181,14 @@ function local_delivery($importer,$data) {
                                        $datarray['type'] = 'activity';
                                        $datarray['gravity'] = GRAVITY_LIKE;
                                        $datarray['last-child'] = 0;
+                                       // only one like or dislike per person
+                                       $r = q("select id from item where uid = %d and `contact-id` = %d and verb ='%s' and deleted = 0 limit 1",
+                                               intval($datarray['uid']),
+                                               intval($datarray['contact-id']),
+                                               dbesc($datarray['verb'])
+                                       );
+                                       if($r && count($r))
+                                               continue; 
                                }
 
                                if(($datarray['verb'] === ACTIVITY_TAG) && ($datarray['object-type'] === ACTIVITY_OBJ_TAGTERM)) {
@@ -2134,6 +2268,7 @@ function local_delivery($importer,$data) {
                                                                'language'     => $importer['language'],
                                                                'to_name'      => $importer['username'],
                                                                'to_email'     => $importer['email'],
+                                                               'uid'          => $importer['importer_uid'],
                                                                'item'         => $datarray,
                                                                'link'             => $a->get_baseurl() . '/display/' . $importer['nickname'] . '/' . $posted_id,
                                                                'source_name'  => stripslashes($datarray['author-name']),
@@ -2141,12 +2276,14 @@ function local_delivery($importer,$data) {
                                                                'source_photo' => ((link_compare($datarray['author-link'],$importer['url'])) 
                                                                        ? $importer['thumb'] : $datarray['author-avatar']),
                                                                'verb'         => ACTIVITY_POST,
-                                                               'otype'        => 'item'
+                                                               'otype'        => 'item',
+                                                               'parent'       => $parent,
 
                                                        ));
 
                                                }
                                        }
+
                                        return 0;
                                        // NOTREACHED
                                }
@@ -2167,7 +2304,8 @@ function local_delivery($importer,$data) {
 
                                if(count($r)) {
                                        if((x($datarray,'edited') !== false) && (datetime_convert('UTC','UTC',$datarray['edited']) !== $r[0]['edited'])) {  
-                                               $r = q("UPDATE `item` SET `body` = '%s', `edited` = '%s' WHERE `uri` = '%s' AND `uid` = %d LIMIT 1",
+                                               $r = q("UPDATE `item` SET `title` = '%s', `body` = '%s', `edited` = '%s' WHERE `uri` = '%s' AND `uid` = %d LIMIT 1",
+                                                       dbesc($datarray['title']),
                                                        dbesc($datarray['body']),
                                                        dbesc(datetime_convert('UTC','UTC',$datarray['edited'])),
                                                        dbesc($item_id),
@@ -2200,6 +2338,15 @@ function local_delivery($importer,$data) {
                                if(($datarray['verb'] == ACTIVITY_LIKE) || ($datarray['verb'] == ACTIVITY_DISLIKE)) {
                                        $datarray['type'] = 'activity';
                                        $datarray['gravity'] = GRAVITY_LIKE;
+                                       // only one like or dislike per person
+                                       $r = q("select id from item where uid = %d and `contact-id` = %d and verb ='%s' and deleted = 0 limit 1",
+                                               intval($datarray['uid']),
+                                               intval($datarray['contact-id']),
+                                               dbesc($datarray['verb'])
+                                       );
+                                       if($r && count($r))
+                                               continue; 
+
                                }
 
                                if(($datarray['verb'] === ACTIVITY_TAG) && ($datarray['object-type'] === ACTIVITY_OBJ_TAGTERM)) {
@@ -2233,38 +2380,51 @@ function local_delivery($importer,$data) {
                        
                                if($datarray['type'] != 'activity') {
 
-                                       $myconv = q("SELECT `author-link`, `author-avatar` FROM `item` WHERE `parent-uri` = '%s' AND `uid` = %d AND `parent` != 0 ",
+                                       $myconv = q("SELECT `author-link`, `author-avatar`, `parent` FROM `item` WHERE `parent-uri` = '%s' AND `uid` = %d AND `parent` != 0 ",
                                                dbesc($parent_uri),
                                                intval($importer['importer_uid'])
                                        );
 
                                        if(count($myconv)) {
                                                $importer_url = $a->get_baseurl() . '/profile/' . $importer['nickname'];
-                                               foreach($myconv as $conv) {
 
-                                                       if(! link_compare($conv['author-link'],$importer_url))
-                                                               continue;
-
-                                                       require_once('include/enotify.php');
+                                               // first make sure this isn't our own post coming back to us from a wall-to-wall event
+                                               if(! link_compare($datarray['author-link'],$importer_url)) {
 
-                                                       notification(array(
-                                                               'type'         => NOTIFY_COMMENT,
-                                                               'notify_flags' => $importer['notify-flags'],
-                                                               'language'     => $importer['language'],
-                                                               'to_name'      => $importer['username'],
-                                                               'to_email'     => $importer['email'],
-                                                               'item'         => $datarray,
-                                                               'link'             => $a->get_baseurl() . '/display/' . $importer['nickname'] . '/' . $posted_id,
-                                                               'source_name'  => stripslashes($datarray['author-name']),
-                                                               'source_link'  => $datarray['author-link'],
-                                                               'source_photo' => ((link_compare($datarray['author-link'],$importer['url'])) 
-                                                                       ? $importer['thumb'] : $datarray['author-avatar']),
-                                                               'verb'         => ACTIVITY_POST,
-                                                               'otype'        => 'item'
+                                                       
+                                                       foreach($myconv as $conv) {
 
-                                                       ));
+                                                               // now if we find a match, it means we're in this conversation
+       
+                                                               if(! link_compare($conv['author-link'],$importer_url))
+                                                                       continue;
 
-                                                       break;
+                                                               require_once('include/enotify.php');
+                                                               
+                                                               $conv_parent = $conv['parent'];
+
+                                                               notification(array(
+                                                                       'type'         => NOTIFY_COMMENT,
+                                                                       'notify_flags' => $importer['notify-flags'],
+                                                                       'language'     => $importer['language'],
+                                                                       'to_name'      => $importer['username'],
+                                                                       'to_email'     => $importer['email'],
+                                                                       'uid'          => $importer['importer_uid'],
+                                                                       'item'         => $datarray,
+                                                                       'link'             => $a->get_baseurl() . '/display/' . $importer['nickname'] . '/' . $posted_id,
+                                                                       'source_name'  => stripslashes($datarray['author-name']),
+                                                                       'source_link'  => $datarray['author-link'],
+                                                                       'source_photo' => ((link_compare($datarray['author-link'],$importer['url'])) 
+                                                                               ? $importer['thumb'] : $datarray['author-avatar']),
+                                                                       'verb'         => ACTIVITY_POST,
+                                                                       'otype'        => 'item',
+                                                                       'parent'       => $conv_parent,
+
+                                                               ));
+
+                                                               // only send one notification
+                                                               break;
+                                                       }
                                                }
                                        }
                                }
@@ -2309,7 +2469,8 @@ function local_delivery($importer,$data) {
 
                        if(count($r)) {
                                if((x($datarray,'edited') !== false) && (datetime_convert('UTC','UTC',$datarray['edited']) !== $r[0]['edited'])) {  
-                                       $r = q("UPDATE `item` SET `body` = '%s', `edited` = '%s' WHERE `uri` = '%s' AND `uid` = %d LIMIT 1",
+                                       $r = q("UPDATE `item` SET `title` = '%s', `body` = '%s', `edited` = '%s' WHERE `uri` = '%s' AND `uid` = %d LIMIT 1",
+                                               dbesc($datarray['title']),
                                                dbesc($datarray['body']),
                                                dbesc(datetime_convert('UTC','UTC',$datarray['edited'])),
                                                dbesc($item_id),
@@ -2334,12 +2495,24 @@ function local_delivery($importer,$data) {
                        // This is my contact on another system, but it's really me.
                        // Turn this into a wall post.
 
-                       if($contact['remote_self'])
+                       if($importer['remote_self'])
                                $datarray['wall'] = 1;
 
                        $datarray['parent-uri'] = $item_id;
                        $datarray['uid'] = $importer['importer_uid'];
                        $datarray['contact-id'] = $importer['id'];
+
+                       if(! link_compare($datarray['owner-link'],$contact['url'])) {
+                               // The item owner info is not our contact. It's OK and is to be expected if this is a tgroup delivery, 
+                               // but otherwise there's a possible data mixup on the sender's system.
+                               // the tgroup delivery code called from item_store will correct it if it's a forum,
+                               // but we're going to unconditionally correct it here so that the post will always be owned by our contact. 
+                               logger('local_delivery: Correcting item owner.', LOGGER_DEBUG);
+                               $datarray['owner-name']   = $importer['senderName'];
+                               $datarray['owner-link']   = $importer['url'];
+                               $datarray['owner-avatar'] = $importer['thumb'];
+                       }
+
                        $r = item_store($datarray);
                        continue;
                }
@@ -2805,7 +2978,7 @@ function drop_item($id,$interactive = true) {
 
                // delete the item
 
-               $r = q("UPDATE `item` SET `deleted` = 1, `body` = '', `edited` = '%s', `changed` = '%s' WHERE `id` = %d LIMIT 1",
+               $r = q("UPDATE `item` SET `deleted` = 1, `title` = '', `body` = '', `edited` = '%s', `changed` = '%s' WHERE `id` = %d LIMIT 1",
                        dbesc(datetime_convert()),
                        dbesc(datetime_convert()),
                        intval($item['id'])
@@ -2838,7 +3011,7 @@ function drop_item($id,$interactive = true) {
                // If it's the parent of a comment thread, kill all the kids
 
                if($item['uri'] == $item['parent-uri']) {
-                       $r = q("UPDATE `item` SET `deleted` = 1, `edited` = '%s', `changed` = '%s', `body` = '' 
+                       $r = q("UPDATE `item` SET `deleted` = 1, `edited` = '%s', `changed` = '%s', `body` = '' , `title` = ''
                                WHERE `parent-uri` = '%s' AND `uid` = %d ",
                                dbesc(datetime_convert()),
                                dbesc(datetime_convert()),