]> git.mxchange.org Git - friendica.git/commitdiff
workflow for federated/non-dfrn followers
authorMike Macgirvin <mike@macgirvin.com>
Mon, 25 Oct 2010 03:39:24 +0000 (20:39 -0700)
committerMike Macgirvin <mike@macgirvin.com>
Mon, 25 Oct 2010 03:39:24 +0000 (20:39 -0700)
16 files changed:
boot.php
include/items.php
include/notifier.php
include/poller.php
include/salmon.php
mod/contacts.php
mod/dfrn_confirm.php
mod/dfrn_notify.php
mod/network.php
mod/notifications.php
mod/salmon.php
view/acl_selectors.php
view/intros.tpl
view/magicsig.tpl [new file with mode: 0644]
view/netfriend.tpl [new file with mode: 0644]
view/theme/default/style.css

index 7885bb4ea466f6592e10e74193283fa8776ea638..8c92487035d2e7545c4c46de68f764463e28dc72 100644 (file)
--- a/boot.php
+++ b/boot.php
@@ -52,10 +52,12 @@ define ( 'NAMESPACE_DFRN' ,           'http://purl.org/macgirvin/dfrn/1.0' );
 define ( 'NAMESPACE_THREAD' ,         'http://purl.org/syndication/thread/1.0' );
 define ( 'NAMESPACE_TOMB' ,           'http://purl.org/atompub/tombstones/1.0' );
 define ( 'NAMESPACE_ACTIVITY',        'http://activitystrea.ms/spec/1.0/' );
-define ( 'NAMESPACE_ACTIVITY_SCHEMA', 'http://activitystrea.ms/schema/1.0/');
-define ( 'NAMESPACE_SALMON_ME',       'http://salmon-protocol.org/ns/magic-env');
-define ( 'NAMESPACE_OSTATUSSUB',      'http://ostatus.org/schema/1.0/subscribe');
-define ( 'NAMESPACE_GEORSS',          'http://www.georss.org/georss');
+define ( 'NAMESPACE_ACTIVITY_SCHEMA', 'http://activitystrea.ms/schema/1.0/' );
+define ( 'NAMESPACE_SALMON_ME',       'http://salmon-protocol.org/ns/magic-env' );
+define ( 'NAMESPACE_OSTATUSSUB',      'http://ostatus.org/schema/1.0/subscribe' );
+define ( 'NAMESPACE_GEORSS',          'http://www.georss.org/georss' );
+define ( 'NAMESPACE_POCO',            'http://portablecontacts.net/spec/1.0' );
+define ( 'NAMESPACE_FEED',            'http://schemas.google.com/g/2010#updates-from' );
 
 // activity stream defines
 
@@ -961,11 +963,11 @@ function webfinger($s) {
        if(strlen($host)) {
                $tpl = fetch_lrdd_template($host);
                if(strlen($tpl)) {
-                       $pxrd = str_replace('{uri}', urlencode('acct://'.$s), $tpl);
+                       $pxrd = str_replace('{uri}', urlencode('acct:'.$s), $tpl);
                        $links = fetch_xrd_links($pxrd);
                        if(! count($links)) {
-                               // try without the double slashes
-                               $pxrd = str_replace('{uri}', urlencode('acct:'.$s), $tpl);
+                               // try with double slashes
+                               $pxrd = str_replace('{uri}', urlencode('acct://'.$s), $tpl);
                                $links = fetch_xrd_links($pxrd);
                        }
                        return $links;
@@ -974,6 +976,54 @@ function webfinger($s) {
        return array();
 }}
 
+if(! function_exists('lrdd')) {
+function lrdd($uri) {
+
+       $a = get_app();
+
+       if(strstr($uri,'@')) {  
+               return(webfinger($uri));
+       }
+       else {
+               $html = fetch_url($uri);
+               $headers = $a->get_curl_headers();
+               $lines = explode("\n",$headers);
+               if(count($lines)) {
+                       foreach($lines as $line) {                              
+                               // TODO alter the following regex to support multiple relations (space separated)
+                               if((stristr($line,'link:')) && preg_match('/<([^>].*)>.*rel\=[\'\"]lrdd[\'\"]/',$line,$matches)) {
+                                       $link = $matches[1];
+                                       break;
+                               }
+                       }
+               }
+               if(! isset($link)) {
+                       // parse the page of the supplied URL looking for rel links
+
+                       require_once('library/HTML5/Parser.php');
+                       $dom = HTML5_Parser::parse($html);
+
+                       if($dom) {
+                               $items = $dom->getElementsByTagName('link');
+
+                               foreach($items as $item) {
+                                       $x = $item->getAttribute('rel');
+                                       if($x == "lrdd") {
+                                               $link = $item->getAttribute('href');
+                                               break;
+                                       }
+                               }
+                       }
+               }
+
+               if(isset($link))
+                       return(fetch_xrd_links($link));
+       }
+       return array();
+}}
+
+
+
 // Given a host name, locate the LRDD template from that
 // host. Returns the LRDD template or an empty string on
 // error/failure.
index e44892316b462a0ff3cefdf7fb546ce759d33430..6cdf5f0f5b6170d57b5174445464d2c4a2352204 100644 (file)
@@ -267,28 +267,89 @@ function construct_activity($item) {
 
 
 
-function get_atom_elements($item) {
+function get_atom_elements($feed,$item) {
 
        require_once('library/HTMLPurifier.auto.php');
        require_once('include/html2bbcode.php');
 
-       $res = array();
+       $best_photo = array();
 
-       $raw_author = $item->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10,'author');
-       if($raw_author) {
-               if($raw_author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['link'][0]['attribs']['']['rel'] === 'photo')
-               $res['author-avatar'] = unxmlify($raw_author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['link'][0]['attribs']['']['href']);
-       }
+       $res = array();
 
        $author = $item->get_author();
        $res['author-name'] = unxmlify($author->get_name());
        $res['author-link'] = unxmlify($author->get_link());
-       if(! $res['author-avatar'])
-               $res['author-avatar'] = unxmlify($author->get_avatar());
        $res['uri'] = unxmlify($item->get_id());
        $res['title'] = unxmlify($item->get_title());
        $res['body'] = unxmlify($item->get_content());
 
+
+       // look for a photo. We should check media size and find the best one,
+       // but for now let's just find any author photo
+
+       $rawauthor = $item->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10,'author');
+
+       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($link['attribs']['']['rel'] === 'photo' || $link['attribs']['']['rel'] === 'avatar')
+                                       $res['author-avatar'] = unxmlify($link['attribs']['']['href']);
+                       }
+               }
+       }                       
+
+       $rawactor = $item->get_item_tags(NAMESPACE_ACTIVITY, 'actor');
+
+       if($rawactor && $rawactor[0]['child'][NAMESPACE_ACTIVITY]['object-type'][0]['data'] === ACTIVITY_OBJ_PERSON) {
+               $base = $rawactor[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['link'];
+               if($base && count($base)) {
+                       foreach($base as $link) {
+                               if($link['attribs']['']['rel'] === 'alternate' && (! $res['author-link']))
+                                       $res['author-link'] = unxmlify($link['attribs']['']['href']);
+                               if(! $res['author-avatar']) {
+                                       if($link['attribs']['']['rel'] === 'avatar' || $link['attribs']['']['rel'] === 'photo')
+                                               $res['author-avatar'] = unxmlify($link['attribs']['']['href']);
+                               }
+                       }
+               }
+       }
+
+       // No photo/profile-link on the item - look at the feed level
+
+       if((! $res['author-link']) || (! $res['author-avatar'])) {
+               $rawauthor = $feed->get_feed_tags(SIMPLEPIE_NAMESPACE_ATOM_10,'author');
+               if($rawauthor && $rawauthor[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['link']) {
+                       $base = $rawauthor[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['link'];
+                       foreach($base as $link) {
+                               if($link['attribs']['']['rel'] === 'alternate' && (! $res['author-link']))
+                                       $res['author-link'] = unxmlify($link['attribs']['']['href']);
+                               if(! $res['author-avatar']) {
+                                       if($link['attribs']['']['rel'] === 'photo' || $link['attribs']['']['rel'] === 'avatar')
+                                               $res['author-avatar'] = unxmlify($link['attribs']['']['href']);
+                               }
+                       }
+               }                       
+
+               $rawactor = $feed->get_feed_tags(NAMESPACE_ACTIVITY, 'subject');
+
+               if($rawactor && $rawactor[0]['child'][NAMESPACE_ACTIVITY]['object-type'][0]['data'] === ACTIVITY_OBJ_PERSON) {
+                       $base = $rawactor[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['link'];
+
+                       if($base && count($base)) {
+                               foreach($base as $link) {
+                                       if($link['attribs']['']['rel'] === 'alternate' && (! $res['author-link']))
+                                               $res['author-link'] = unxmlify($link['attribs']['']['href']);
+                                       if(! $res['author-avatar']) {
+                                               if($link['attribs']['']['rel'] === 'avatar' || $link['attribs']['']['rel'] === 'photo')
+                                                       $res['author-avatar'] = unxmlify($link['attribs']['']['href']);
+                                       }
+                               }
+                       }
+               }
+       }
+
+
        $maxlen = get_max_import_size();
        if($maxlen && (strlen($res['body']) > $maxlen))
                $res['body'] = substr($res['body'],0, $maxlen);
@@ -310,7 +371,7 @@ function get_atom_elements($item) {
                        '[youtube]$1[/youtube]', $res['body']);
 
                $config = HTMLPurifier_Config::createDefault();
-               $config->set('Core.DefinitionCache', null);
+               $config->set('Cache.DefinitionImpl', null);
 
                // we shouldn't need a whitelist, because the bbcode converter
                // will strip out any unsupported tags.
@@ -353,27 +414,21 @@ function get_atom_elements($item) {
        elseif($rawowner[0]['child'][NAMESPACE_DFRN]['uri'][0]['data'])
                $res['owner-link'] = unxmlify($rawowner[0]['child'][NAMESPACE_DFRN]['uri'][0]['data']);
 
-       if($rawowner[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['link'][0]['attribs']['']['rel'] === 'photo')
-               $res['owner-avatar'] = unxmlify($rawowner[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['link'][0]['attribs']['']['href']);
-       elseif($rawowner[0]['child'][NAMESPACE_DFRN]['avatar'][0]['data'])
-               $res['owner-avatar'] = unxmlify($rawowner[0]['child'][NAMESPACE_DFRN]['avatar'][0]['data']);
+       if($rawowner[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['link']) {
+               $base = $rawowner[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['link'];
+
+               foreach($base as $link) {
+                       if(! $res['owner-avatar']) {
+                               if($link['attribs']['']['rel'] === 'photo' || $link['attribs']['']['rel'] === 'avatar')                 
+                                       $res['owner-avatar'] = unxmlify($link['attribs']['']['href']);
+                       }
+               }
+       }
 
        $rawgeo = $item->get_item_tags(NAMESPACE_GEORSS,'point');
        if($rawgeo)
                $res['coord'] = unxmlify($rawgeo[0]['data']);
 
-       $rawactor = $item->get_item_tags(NAMESPACE_ACTIVITY, 'object');
-       if($rawactor && $rawactor[0]['child'][NAMESPACE_ACTIVITY]['object-type'][0]['data'] === ACTIVITY_OBJ_PERSON) {
-               $base = $rawactor[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['link'];
-               if($base && count($base)) {
-                       foreach($base as $link) {
-                               if($link['attribs']['']['rel'] === 'alternate' && (! $res['author-link']))
-                                       $res['author-link'] = unxmlify($link['attribs']['']['href']);
-                               if($link['attribs']['']['rel'] === 'avatar' && (! $res['author-avatar']))
-                                       $res['author-avatar'] = unxmlify($link['attribs']['']['href']);
-                       }
-               }
-       }
 
        $rawverb = $item->get_item_tags(NAMESPACE_ACTIVITY, 'verb');
        // select between supported verbs
@@ -405,7 +460,7 @@ function get_atom_elements($item) {
                                        '[youtube]$1[/youtube]', $body);
 
                                $config = HTMLPurifier_Config::createDefault();
-                               $config->set('Core.DefinitionCache', null);
+                               $config->set('Cache.DefinitionImpl', null);
 
                                $purifier = new HTMLPurifier($config);
                                $body = $purifier->purify($body);
@@ -423,9 +478,6 @@ function get_atom_elements($item) {
 
 function item_store($arr) {
 
-//print_r($arr);
-
-
        if($arr['gravity'])
                $arr['gravity'] = intval($arr['gravity']);
        elseif($arr['parent-uri'] == $arr['uri'])
@@ -648,6 +700,7 @@ function consume_feed($xml,$importer,$contact, &$hub) {
        $feed->init();
 
        // Check at the feed level for updated contact name and/or photo
+       $debugging = get_config('system','debugging');
 
        $name_updated  = '';
        $new_name = '';
@@ -832,11 +885,13 @@ function consume_feed($xml,$importer,$contact, &$hub) {
                                        }
                                        continue;
                                }
-                               $datarray = get_atom_elements($item);
+                               $datarray = get_atom_elements($feed,$item);
+                               if($contact['network'] === 'stat' && strlen($datarray['title']))
+                                       unset($datarray['title']);
                                $datarray['parent-uri'] = $parent_uri;
                                $datarray['uid'] = $importer['uid'];
                                $datarray['contact-id'] = $contact['id'];
-                               if(($datarray['verb'] == ACTIVITY_LIKE) || ($datarray['verb'] == ACTIVITY_DISLIKE)) {
+                               if(($datarray['verb'] === ACTIVITY_LIKE) || ($datarray['verb'] === ACTIVITY_DISLIKE)) {
                                        $datarray['type'] = 'activity';
                                        $datarray['gravity'] = GRAVITY_LIKE;
                                }
@@ -865,17 +920,23 @@ function consume_feed($xml,$importer,$contact, &$hub) {
                                        }
                                        continue;
                                }
-                               $datarray = get_atom_elements($item);
-                               if(($datarray['verb'] === ACTIVITY_FOLLOW) && (! is_array($contact))) {
-                                       new_follower($importer,$datarray);
+                               $datarray = get_atom_elements($feed,$item);
+
+                               if($datarray['verb'] === ACTIVITY_FOLLOW) {
+                                       if($debugging)
+                                               file_put_contents('salmon.out',"\n" . 'New follower.' . "\n", FILE_APPEND);
+                                       new_follower($importer,$contact,$datarray,$item);
                                        return;
                                }
                                if($datarray['verb'] === ACTIVITY_UNFOLLOW)  {
-                                       lose_follower($importer,$contact,$datarray);
+                                       lose_follower($importer,$contact,$datarray,$item);
                                        return;
                                }
                                if(! is_array($contact))
                                        return;
+
+                               if($contact['network'] === 'stat' && strlen($datarray['title']))
+                                       unset($datarray['title']);
                                $datarray['parent-uri'] = $item_id;
                                $datarray['uid'] = $importer['uid'];
                                $datarray['contact-id'] = $contact['id'];
@@ -888,14 +949,76 @@ function consume_feed($xml,$importer,$contact, &$hub) {
 
 }
 
-function new_follower($importer,$datarray) {
+function new_follower($importer,$contact,$datarray,$item) {
+       $url = notags(trim($datarray['author-link']));
+       $name = notags(trim($datarray['author-name']));
+       $photo = notags(trim($datarray['author-avatar']));
+
+       $rawtag = $item->get_item_tags(NAMESPACE_ACTIVITY,'actor');
+       if($rawtag && $rawtag[0]['child'][NAMESPACE_POCO]['preferredUsername'][0]['data'])
+               $nick = $rawtag[0]['child'][NAMESPACE_POCO]['preferredUsername'][0]['data'];
+
+       if(is_array($contact)) {
+               if($contact['network'] == 'stat' && $contact['rel'] == REL_FAN) {
+                       $q("UPDATE `contact` SET `rel` = %d WHERE `id` = %d AND `uid` = %d LIMIT 1",
+                               intval(REL_BUD),
+                               intval($contact['id']),
+                               intval($importer['uid'])
+                       );
+               }
 
+               // send email notification to owner?
+       }
+       else {
+       
+               // create contact record - set to readonly
 
+               $r = q("INSERT INTO `contact` ( `uid`, `created`, `url`, `name`, `nick`, `photo`, `network`, `rel`, 
+                       `blocked`, `readonly`, `pending` )
+                       VALUES ( %d, '%s', '%s', '%s', '%s', '%s', '%s', %d, 0, 1, 1 ) ",
+                       intval($importer['uid']),
+                       dbesc(datetime_convert()),
+                       dbesc($url),
+                       dbesc($name),
+                       dbesc($nick),
+                       dbesc($photo),
+                       dbesc('stat'),
+                       intval(REL_VIP)
+               );
+               $r = q("SELECT `id` FROM `contact` WHERE `uid` = %d AND `url` = '%s' AND `pending` = 1 AND `rel` = %d LIMIT 1",
+                               intval($importer['uid']),
+                               dbesc($url),
+                               intval(REL_VIP)
+               );
+               if(count($r))
+                               $contact_record = $r[0];
+
+               // create notification  
+               $hash = random_string();
+
+               if(is_array($contact_record)) {
+                       $ret = q("INSERT INTO `intro` ( `uid`, `contact-id`, `blocked`, `knowyou`, `hash`, `datetime`)
+                               VALUES ( %d, %d, 0, 0, '%s', '%s' )",
+                               intval($importer['uid']),
+                               intval($contact_record['id']),
+                               dbesc($hash),
+                               dbesc(datetime_convert())
+                       );
+               }
+       }
 }
 
-function lose_follower($importer,$contact,$datarray) {
-
+function lose_follower($importer,$contact,$datarray,$item) {
 
+       if($contact['rel'] == REL_BUD) {
+               q("UPDATE `contact` SET `rel` = %d WHERE `id` = %d LIMIT 1",
+                       intval(REL_FAN),
+                       intval($contact['id'])
+               );
+       }
+       else {
+               contact_remove($contact['id']);
+       }
 }
 
 
index 99b3859960da5dbd4bc0797800550410e27cb9e7..9e4a7102e8f02b31a44cf0fb19bf56fa3de22709 100644 (file)
@@ -87,6 +87,9 @@
        // If this is a public conversation, notify the feed hub
        $notify_hub = true;
 
+       // fill this in with a salmon slap if applicable
+       $slap = '';
+
        if($cmd != 'mail') {
 
                require_once('include/group.php');
                                $actobj = construct_activity($item);
 
                                if($item['id'] == $item_id) {
-                                       $atom .= replace_macros($cmnt_template, array(
+                                       $slap = replace_macros($cmnt_template, array(
                                                '$name'               => xmlify($owner['name']),
                                                '$profile_page'       => xmlify($owner['url']),
                                                '$thumb'              => xmlify($owner['thumb']),
                                        ));
                                }
                        }
+                       $atom .= $slap;
                }
                else {
                        foreach($items as $item) {
 
        // delivery loop
 
+
+
        foreach($r as $contact) {
                if($contact['self'])
                        continue;
                                $deliver_status = dfrn_deliver($owner,$contact,$atom,$debugging);
                                break;
                        default:
+                               if($followup) {
+                                       require_once('include/salmon.php');
+                                       slapper($owner,$contact,$slap);
+                               }
                                break;
                }
 
index 720163fef7b29cdb180ebf5d48361b0755daa652..b88b131e23a2f05da69eaeeb198bb19d8772db9f 100644 (file)
@@ -22,7 +22,8 @@
        $a->set_baseurl(get_config('system','url'));
 
        $contacts = q("SELECT * FROM `contact` 
-               WHERE `network` = 'dfrn' AND ( `dfrn-id` != '' OR (`issued-id` != '' AND `duplex` = 1)) 
+               WHERE ( ( `network` = 'dfrn' AND ( `dfrn-id` != '' OR (`issued-id` != '' AND `duplex` = 1)))
+               OR ( `network` = 'stat' AND `poll` != '' ) ) 
                AND `self` = 0 AND `blocked` = 0 AND `readonly` = 0 ORDER BY RAND()");
 
        if(! count($contacts))
                        : datetime_convert('UTC','UTC',$contact['last-update'], ATOM_TIME)
                );
 
-               $idtosend = $orig_id = (($contact['dfrn-id']) ? $contact['dfrn-id'] : $contact['issued-id']);
+               if($contact['network'] === 'dfrn') {
 
-               if(intval($contact['duplex']) && $contact['dfrn-id'])
-                       $idtosend = '0:' . $orig_id;
-               if(intval($contact['duplex']) && $contact['issued-id'])
-                       $idtosend = '1:' . $orig_id;            
+                       $idtosend = $orig_id = (($contact['dfrn-id']) ? $contact['dfrn-id'] : $contact['issued-id']);
 
-               $url = $contact['poll'] . '?dfrn_id=' . $idtosend 
-                       . '&dfrn_version=' . DFRN_PROTOCOL_VERSION 
-                       . '&type=data&last_update=' . $last_update ;
+                       if(intval($contact['duplex']) && $contact['dfrn-id'])
+                               $idtosend = '0:' . $orig_id;
+                       if(intval($contact['duplex']) && $contact['issued-id'])
+                               $idtosend = '1:' . $orig_id;            
 
-               $xml = fetch_url($url);
+                       $url = $contact['poll'] . '?dfrn_id=' . $idtosend 
+                               . '&dfrn_version=' . DFRN_PROTOCOL_VERSION 
+                               . '&type=data&last_update=' . $last_update ;
+       
+                       $xml = fetch_url($url);
 
-               if($debugging) {
-                       echo "URL: " . $url . "\n";
-                       echo "XML: " . $xml . "\n";
-               }
+                       if($debugging) {
+                               echo "URL: " . $url . "\n";
+                               echo "XML: " . $xml . "\n";
+                       }
 
-               if(! $xml) {
-                       // dead connection - might be a transient event, or this might
-                       // mean the software was uninstalled or the domain expired. 
-                       // Will keep trying for one month.
-                       mark_for_death($contact);
-                       continue;
-               }
+                       if(! $xml) {
+                               // dead connection - might be a transient event, or this might
+                               // mean the software was uninstalled or the domain expired. 
+                               // Will keep trying for one month.
+                               mark_for_death($contact);
+                               continue;
+                       }
 
 
-               $res = simplexml_load_string($xml);
+                       $res = simplexml_load_string($xml);
 
-               if(intval($res->status) == 1) {
-                       // we may not be friends anymore. Will keep trying for one month.
-                       mark_for_death($contact);
-               }
-               else {
-                       if($contact['term-date'] != '0000-00-00 00:00:00')
-                               unmark_for_death($contact);
-               }
+                       if(intval($res->status) == 1) {
+                               // we may not be friends anymore. Will keep trying for one month.
+                               mark_for_death($contact);
+                       }
+                       else {
+                               if($contact['term-date'] != '0000-00-00 00:00:00')
+                                       unmark_for_death($contact);
+                       }
 
-               if((intval($res->status) != 0) || (! strlen($res->challenge)) || (! strlen($res->dfrn_id)))
-                       continue;
+                       if((intval($res->status) != 0) || (! strlen($res->challenge)) || (! strlen($res->dfrn_id)))
+                               continue;
 
-               $postvars = array();
+                       $postvars = array();
 
-               $sent_dfrn_id = hex2bin($res->dfrn_id);
-               $challenge    = hex2bin($res->challenge);
+                       $sent_dfrn_id = hex2bin($res->dfrn_id);
+                       $challenge    = hex2bin($res->challenge);
 
-               $final_dfrn_id = '';
+                       $final_dfrn_id = '';
 
-               if(($contact['duplex']) && strlen($contact['prvkey'])) {
-                       openssl_private_decrypt($sent_dfrn_id,$final_dfrn_id,$contact['prvkey']);
-                       openssl_private_decrypt($challenge,$postvars['challenge'],$contact['prvkey']);
+                       if(($contact['duplex']) && strlen($contact['prvkey'])) {
+                               openssl_private_decrypt($sent_dfrn_id,$final_dfrn_id,$contact['prvkey']);
+                               openssl_private_decrypt($challenge,$postvars['challenge'],$contact['prvkey']);
+                       }
+                       else {
+                               openssl_public_decrypt($sent_dfrn_id,$final_dfrn_id,$contact['pubkey']);
+                               openssl_public_decrypt($challenge,$postvars['challenge'],$contact['pubkey']);
+                       }
 
-               }
-               else {
-                       openssl_public_decrypt($sent_dfrn_id,$final_dfrn_id,$contact['pubkey']);
-                       openssl_public_decrypt($challenge,$postvars['challenge'],$contact['pubkey']);
-               }
+                       $final_dfrn_id = substr($final_dfrn_id, 0, strpos($final_dfrn_id, '.'));
+
+                       if(strpos($final_dfrn_id,':') == 1)
+                               $final_dfrn_id = substr($final_dfrn_id,2);
 
-               $final_dfrn_id = substr($final_dfrn_id, 0, strpos($final_dfrn_id, '.'));
+                       if($final_dfrn_id != $orig_id) {
 
-               if(strpos($final_dfrn_id,':') == 1)
-                       $final_dfrn_id = substr($final_dfrn_id,2);
+                               // did not decode properly - cannot trust this site 
+                               continue;
+                       }
 
-               if($final_dfrn_id != $orig_id) {
+                       $postvars['dfrn_id'] = $idtosend;
+                       $postvars['dfrn_version'] = DFRN_PROTOCOL_VERSION;
 
-                       // did not decode properly - cannot trust this site 
-                       continue;
+                       $xml = post_url($contact['poll'],$postvars);
                }
+               else {
+                       // $contact['network'] !== 'dfrn'
 
-               $postvars['dfrn_id'] = $idtosend;
-               $postvars['dfrn_version'] = DFRN_PROTOCOL_VERSION;
-
-               $xml = post_url($contact['poll'],$postvars);
+                       $xml = fetch_url($contact['poll']);
+               }
 
                if($debugging) {
                        echo "XML response:" . $xml . "\n";
                if(! strlen($xml))
                        continue;
 
-
                consume_feed($xml,$importer,$contact,$hub);
                
-
                if((strlen($hub)) && ($contact['rel'] == REL_BUD) && ($contact['priority'] == 0)) {
                        $hubs = explode(',', $hub);
                        if(count($hubs)) {
                        intval($contact['id'])
                );
 
-       }
+               // loop - next contact
+       }  
                
        killme();
 
index 92ec571b38f6e9b44cd4b85719cd3d4561dd7de6..c5ad3e82561c8a304cc6f71541d84bbdd14caab4 100644 (file)
@@ -33,61 +33,9 @@ function get_salmon_key($uri,$keyhash) {
        if($debugging)          
                file_put_contents('salmon.out', "\n" . 'Fetch key' . "\n", FILE_APPEND);
 
-       if(strstr($uri,'@')) {  
-               $arr = webfinger($uri);
-               if($debugging)
-                       file_put_contents('salmon.out', "\n" . 'Fetch key from webfinger' . "\n", FILE_APPEND);
-       }
-       else {
-               $html = fetch_url($uri);
-               $a = get_app();
-               $h = $a->get_curl_headers();
-               if($debugging)
-                       file_put_contents('salmon.out', "\n" . 'Fetch key via HTTP header: ' . $h . "\n", FILE_APPEND);
-
-               $l = explode("\n",$h);
-               if(count($l)) {
-                       foreach($l as $line) {                          
-                               // TODO alter the following regex to support multiple relations (space separated)
-                               if((stristr($line,'link:')) && preg_match('/<([^>].*)>.*rel\=[\'\"]lrdd[\'\"]/',$line,$matches)) {
-                                       $link = $matches[1];
-                                       if($debugging)
-                                               file_put_contents('salmon.out', "\n" . 'Fetch key via HTML Link: ' . $link . "\n", FILE_APPEND);
-                                       break;
-                               }
-                       }
-               }
-
-               if(! isset($link)) {
-
-                       // parse the page of the supplied URL looking for rel links
-
-                       require_once('library/HTML5/Parser.php');
-                       $dom = HTML5_Parser::parse($html);
-
-                       if(! $dom)
-                               return '';
+       $arr = lrdd($uri);
 
-                       $items = $dom->getElementsByTagName('link');
-
-                       foreach($items as $item) {
-                               $x = $item->getAttribute('rel');
-                               if($x == "lrdd") {
-                                       $link = $item->getAttribute('href');
-                                       if($debugging)
-                                               file_put_contents('salmon.out', "\n" . 'Fetch key via HTML body' . $link . "\n", FILE_APPEND);
-                                       break;
-                               }
-                       }
-               }
-
-               if(! isset($link))
-                       return '';
-
-               $arr = fetch_xrd_links($link);
-       }
-
-       if($arr) {
+       if(is_array($arr)) {
                foreach($arr as $a) {
                        if($a['@attributes']['rel'] === 'magic-public-key') {
                                $ret[] = $a['@attributes']['href'];
@@ -140,4 +88,60 @@ function get_salmon_key($uri,$keyhash) {
 
        
                
-                               
\ No newline at end of file
+function slapper($owner,$contact,$slap) {
+
+
+       // does contact have a salmon endpoint? 
+
+       if(! strlen($contact['notify']))
+               return;
+
+       // add all namespaces to item
+
+$namespaces = <<< EOT
+<entry xmlns="http://www.w3.org/2005/Atom"
+      xmlns:thr="http://purl.org/syndication/thread/1.0"
+      xmlns:at="http://purl.org/atompub/tombstones/1.0"
+      xmlns:media="http://purl.org/syndication/atommedia"
+      xmlns:dfrn="http://purl.org/macgirvin/dfrn/1.0" 
+      xmlns:as="http://activitystrea.ms/spec/1.0/"
+      xmlns:georss="http://www.georss.org/georss" >
+EOT;
+
+       $slap = str_replace('<entry>',$namespaces,$slap);
+       
+       // create a magic envelope
+
+       $data      = base64url_encode($slap);
+       $data_type = 'application/atom+xml';
+       $encoding  = 'base64url';
+       $algorithm = 'RSA-SHA256';
+       $keyhash   = base64url_encode(hash('sha256',salmon_key($owner['spubkey'])));
+
+       // Setup RSA stuff to PKCS#1 sign the data
+
+       set_include_path(get_include_path() . PATH_SEPARATOR . 'phpsec');
+
+       require_once('phpsec/Crypt/RSA.php');
+
+    $rsa = new CRYPT_RSA();
+    $rsa->signatureMode = CRYPT_RSA_SIGNATURE_PKCS1;
+    $rsa->setHash('sha256');
+       $rsa->loadKey($owner['sprvkey']);
+
+    $signature = $rsa->sign($data);
+
+       $salmon_tpl = load_view_file('view/magicsig.tpl');
+       $salmon = replace_macros($salmon_tpl,array(
+               '$data'      => $data,
+               '$encoding'  => $encoding,
+               '$algorithm' => $algorithm,
+               '$keyhash'   => $keyhash,
+               '$signature' => $signature
+       ));
+
+       // slap them 
+       post_url($contact['notify'],$salmon);
+
+       return;
+}
\ No newline at end of file
index 746331ea540ac255a634f1cb34770f449cf29e6b..bd5bf8ea80b9c56d3acbf4d55aa342a1224b6673 100644 (file)
@@ -271,7 +271,6 @@ function contacts_content(&$a) {
                                default:
                                        break;
                        }
-
                        if(($rr['network'] === 'dfrn') && ($rr['rel'])) {
                                $url = "redir/{$rr['id']}";
                                $sparkle = ' class="sparkle" ';
index b4ca74889b50fbfe0b9e1d40705e60801fd208f5..cc1edea229baee150eb6dca2aa82c2b5b6491837 100644 (file)
@@ -7,7 +7,7 @@ function dfrn_confirm_post(&$a,$handsfree = null) {
        if(is_array($handsfree)) {
 
                // called directly from dfrn_request due to automatic friend acceptance
-               // any $_POST parameters we might need are supplied in the $handsfree array
+               // any $_POST parameters we may require are supplied in the $handsfree array
 
                $node = $handsfree['node'];
                $a->interactive = false; // notice() becomes a no-op since nobody is there to see it
@@ -19,12 +19,12 @@ function dfrn_confirm_post(&$a,$handsfree = null) {
        }
 
                // Main entry point. Our user received a friend request notification (perhaps 
-               // from another site) and clicked 'Accept'. $POST['source_url'] is not set.
+               // from another site) and clicked 'Approve'. $POST['source_url'] is not set.
                // OR we have been called directly from dfrn_request ($handsfree != null) due to 
                // this being a page type which supports automatic friend acceptance.
 
        if(! x($_POST,'source_url')) {
-               
+
                $uid = ((is_array($handsfree)) ? $handsfree['uid'] : local_user());
 
                if(! $uid) {
@@ -42,7 +42,7 @@ function dfrn_confirm_post(&$a,$handsfree = null) {
                }       
 
 
-               // These come from the friend request notification form or $handsfree reply.
+               // These come from either the friend request notification form or $handsfree array.
 
                if(is_array($handsfree)) {
                        $dfrn_id = $handsfree['dfrn_id'];
@@ -53,13 +53,16 @@ function dfrn_confirm_post(&$a,$handsfree = null) {
                        $dfrn_id  = ((x($_POST,'dfrn_id')) ? notags(trim($_POST['dfrn_id'])) : "");
                        $intro_id = intval($_POST['intro_id']);
                        $duplex   = intval($_POST['duplex']);
+                       $cid      = intval($_POST['contact_id']);
                }
 
                // The other person will have been issued an ID when they first requested friendship.
                // Locate their record. At this time, their record will have both pending and blocked set to 1. 
+               // There won't be any dfrn_id if this is a network follower, so use the contact_id instead.
 
-               $r = q("SELECT * FROM `contact` WHERE `issued-id` = '%s' AND `uid` = %d LIMIT 1",
+               $r = q("SELECT * FROM `contact` WHERE ( ( `issued-id` != '' AND `issued-id` = '%s' ) OR ( `id` = %d AND `id` != 0 ) ) AND `uid` = %d LIMIT 1",
                                dbesc($dfrn_id),
+                               intval($cid),
                                intval($uid)
                );
 
@@ -68,153 +71,158 @@ function dfrn_confirm_post(&$a,$handsfree = null) {
                        return;
                }
 
-               $contact_id   = $r[0]['id'];
-               $relation     = $r[0]['rel'];
-               $site_pubkey  = $r[0]['site-pubkey'];
-               $dfrn_confirm = $r[0]['confirm'];
-               $aes_allow    = $r[0]['aes_allow'];
+               $contact = $r[0];
 
+               $contact_id   = $contact['id'];
+               $relation     = $contact['rel'];
+               $site_pubkey  = $contact['site-pubkey'];
+               $dfrn_confirm = $contact['confirm'];
+               $aes_allow    = $contact['aes_allow'];
 
-               // Generate a key pair for all further communications with this person.
-               // We have a keypair for every contact, and a site key for unknown people.
-               // This provides a means to carry on relationships with other people if 
-               // any single key is compromised. It is a robust key. We're much more 
-               // worried about key leakage than anybody cracking it.  
 
-               $res = openssl_pkey_new(array(
-                       'digest_alg' => 'whirlpool',
-                       'private_key_bits' => 4096,
-                       'encrypt_key' => false )
-               );
+               if($contact['network'] === 'dfrn') {
 
+                       // Generate a key pair for all further communications with this person.
+                       // We have a keypair for every contact, and a site key for unknown people.
+                       // This provides a means to carry on relationships with other people if 
+                       // any single key is compromised. It is a robust key. We're much more 
+                       // worried about key leakage than anybody cracking it.  
 
-               $private_key = '';
+                       $res = openssl_pkey_new(array(
+                               'digest_alg' => 'whirlpool',
+                               'private_key_bits' => 4096,
+                               'encrypt_key' => false )
+                       );
 
-               openssl_pkey_export($res, $private_key);
 
-               $pubkey = openssl_pkey_get_details($res);
-               $public_key = $pubkey["key"];
+                       $private_key = '';
 
-               // Save the private key. Send them the public key.
+                       openssl_pkey_export($res, $private_key);
 
-               $r = q("UPDATE `contact` SET `prvkey` = '%s' WHERE `id` = %d AND `uid` = %d LIMIT 1",
-                       dbesc($private_key),
-                       intval($contact_id),
-                       intval($uid) 
-               );
+                       $pubkey = openssl_pkey_get_details($res);
+                       $public_key = $pubkey["key"];
 
-               $params = array();
+                       // Save the private key. Send them the public key.
 
-               // Per the protocol document, we will verify both ends by encrypting the dfrn_id with our 
-               // site private key (person on the other end can decrypt it with our site public key).
-               // Then encrypt our profile URL with the other person's site public key. They can decrypt
-               // it with their site private key. If the decryption on the other end fails for either
-               // item, it indicates tampering or key failure on at least one site and we will not be 
-               // able to provide a secure communication pathway.
+                       $r = q("UPDATE `contact` SET `prvkey` = '%s' WHERE `id` = %d AND `uid` = %d LIMIT 1",
+                               dbesc($private_key),
+                               intval($contact_id),
+                               intval($uid) 
+                       );
 
-               // If other site is willing to accept full encryption, (aes_allow is 1 AND we have php5.3 
-               // or later) then we encrypt the personal public key we send them using AES-256-CBC and a 
-               // random key which is encrypted with their site public key.  
+                       $params = array();
 
-               $src_aes_key = random_string();
+                       // Per the protocol document, we will verify both ends by encrypting the dfrn_id with our 
+                       // site private key (person on the other end can decrypt it with our site public key).
+                       // Then encrypt our profile URL with the other person's site public key. They can decrypt
+                       // it with their site private key. If the decryption on the other end fails for either
+                       // item, it indicates tampering or key failure on at least one site and we will not be 
+                       // able to provide a secure communication pathway.
 
-               $result = '';
-               openssl_private_encrypt($dfrn_id,$result,$user[0]['prvkey']);
+                       // If other site is willing to accept full encryption, (aes_allow is 1 AND we have php5.3 
+                       // or later) then we encrypt the personal public key we send them using AES-256-CBC and a 
+                       // random key which is encrypted with their site public key.  
 
-               $params['dfrn_id'] = bin2hex($result);
-               $params['public_key'] = $public_key;
+                       $src_aes_key = random_string();
 
+                       $result = '';
+                       openssl_private_encrypt($dfrn_id,$result,$user[0]['prvkey']);
 
-               $my_url = $a->get_baseurl() . '/profile/' . $user[0]['nickname'];
+                       $params['dfrn_id'] = bin2hex($result);
+                       $params['public_key'] = $public_key;
 
-               openssl_public_encrypt($my_url, $params['source_url'], $site_pubkey);
-               $params['source_url'] = bin2hex($params['source_url']);
 
-               if($aes_allow && function_exists('openssl_encrypt')) {
-                       openssl_public_encrypt($src_aes_key, $params['aes_key'], $site_pubkey);
-                       $params['aes_key'] = bin2hex($params['aes_key']);
-                       $params['public_key'] = bin2hex(openssl_encrypt($public_key,'AES-256-CBC',$src_aes_key));
-               }
+                       $my_url = $a->get_baseurl() . '/profile/' . $user[0]['nickname'];
 
-               $params['dfrn_version'] = DFRN_PROTOCOL_VERSION ;
-               if($duplex == 1)
-                       $params['duplex'] = 1;
+                       openssl_public_encrypt($my_url, $params['source_url'], $site_pubkey);
+                       $params['source_url'] = bin2hex($params['source_url']);
 
-               // POST all this stuff to the other site.
+                       if($aes_allow && function_exists('openssl_encrypt')) {
+                               openssl_public_encrypt($src_aes_key, $params['aes_key'], $site_pubkey);
+                               $params['aes_key'] = bin2hex($params['aes_key']);
+                               $params['public_key'] = bin2hex(openssl_encrypt($public_key,'AES-256-CBC',$src_aes_key));
+                       }
 
-               $res = post_url($dfrn_confirm,$params);
+                       $params['dfrn_version'] = DFRN_PROTOCOL_VERSION ;
+                       if($duplex == 1)
+                               $params['duplex'] = 1;
 
-               // Now figure out what they responded. Try to be robust if the remote site is 
-               // having difficulty and throwing up errors of some kind. 
+                       // POST all this stuff to the other site.
 
-               $leading_junk = substr($res,0,strpos($res,'<?xml'));
+                       $res = post_url($dfrn_confirm,$params);
 
-               $res = substr($res,strpos($res,'<?xml'));
-               if(! strlen($res)) {
+                       // Now figure out what they responded. Try to be robust if the remote site is 
+                       // having difficulty and throwing up errors of some kind. 
 
-                               // No XML at all, this exchange is messed up really bad.
-                               // We shouldn't proceed, because the xml parser might choke,
-                               // and $status is going to be zero, which indicates success.
-                               // We can hardly call this a success.  
+                       $leading_junk = substr($res,0,strpos($res,'<?xml'));
 
-                       notice( t('Response from remote site was not understood.') . EOL);
-                       return;
-               }
+                       $res = substr($res,strpos($res,'<?xml'));
+                       if(! strlen($res)) {
 
-               if(strlen($leading_junk) && get_config('system','debugging')) {
+                                       // No XML at all, this exchange is messed up really bad.
+                                       // We shouldn't proceed, because the xml parser might choke,
+                                       // and $status is going to be zero, which indicates success.
+                                       // We can hardly call this a success.  
+       
+                               notice( t('Response from remote site was not understood.') . EOL);
+                               return;
+                       }
 
-                               // This might be more common. Mixed error text and some XML.
-                               // If we're configured for debugging, show the text. Proceed in either case.
+                       if(strlen($leading_junk) && get_config('system','debugging')) {
+       
+                                       // This might be more common. Mixed error text and some XML.
+                                       // If we're configured for debugging, show the text. Proceed in either case.
 
-                       notice( t('Unexpected response from remote site: ') . EOL . $leading_junk . EOL );
-               }
+                               notice( t('Unexpected response from remote site: ') . EOL . $leading_junk . EOL );
+                       }
 
-               $xml = simplexml_load_string($res);
-               $status = (int) $xml->status;
-               $message = unxmlify($xml->message);   // human readable text of what may have gone wrong.
-               switch($status) {
-                       case 0:
-                               notice( t("Confirmation completed successfully.") . EOL);
-                               if(strlen($message))
-                                       notice( t('Remote site reported: ') . $message . EOL);
-                               break;
-                       case 1:
-                               // birthday paradox - generate new dfrn-id and fall through.
-                               $new_dfrn_id = random_string();
-                               $r = q("UPDATE contact SET `issued-id` = '%s' WHERE `id` = %d AND `uid` = %d LIMIT 1",
-                                       dbesc($new_dfrn_id),
-                                       intval($contact_id),
-                                       intval($uid) 
+                       $xml = simplexml_load_string($res);
+                       $status = (int) $xml->status;
+                       $message = unxmlify($xml->message);   // human readable text of what may have gone wrong.
+                       switch($status) {
+                               case 0:
+                                       notice( t("Confirmation completed successfully.") . EOL);
+                                       if(strlen($message))
+                                               notice( t('Remote site reported: ') . $message . EOL);
+                                       break;
+                               case 1:
+                                       // birthday paradox - generate new dfrn-id and fall through.
+                                       $new_dfrn_id = random_string();
+                                       $r = q("UPDATE contact SET `issued-id` = '%s' WHERE `id` = %d AND `uid` = %d LIMIT 1",
+                                               dbesc($new_dfrn_id),
+                                               intval($contact_id),
+                                               intval($uid) 
+                                       );
+
+                               case 2:
+                                       notice( t("Temporary failure. Please wait and try again.") . EOL);
+                                       if(strlen($message))
+                                               notice( t('Remote site reported: ') . $message . EOL);
+                                       break;
+
+
+                               case 3:
+                                       notice( t("Introduction failed or was revoked.") . EOL);
+                                       if(strlen($message))
+                                               notice( t('Remote site reported: ') . $message . EOL);
+                                       break;
+                               }
+
+                       if(($status == 0) && ($intro_id)) {
+       
+                               // Success. Delete the notification.
+       
+                               $r = q("DELETE FROM `intro` WHERE `id` = %d AND `uid` = %d LIMIT 1",
+                                       intval($intro_id),
+                                       intval($uid)
                                );
-
-                       case 2:
-                               notice( t("Temporary failure. Please wait and try again.") . EOL);
-                               if(strlen($message))
-                                       notice( t('Remote site reported: ') . $message . EOL);
-                               break;
-
-
-                       case 3:
-                               notice( t("Introduction failed or was revoked.") . EOL);
-                               if(strlen($message))
-                                       notice( t('Remote site reported: ') . $message . EOL);
-                               break;
+                               
                        }
 
-               if(($status == 0) && ($intro_id)) {
-
-                       // Success. Delete the notification.
-
-                       $r = q("DELETE FROM `intro` WHERE `id` = %d AND `uid` = %d LIMIT 1",
-                               intval($intro_id),
-                               intval($uid)
-                       );
-                       
+                       if($status != 0) 
+                               return;
                }
 
-               if($status != 0) 
-                       return;
-               
                // We have now established a relationship with the other site.
                // Let's make our own personal copy of their profile photo so we don't have
                // to always load it from their site.
@@ -223,36 +231,29 @@ function dfrn_confirm_post(&$a,$handsfree = null) {
 
                $photo_failure = false;
 
-               $r = q("SELECT `photo` FROM `contact` WHERE `id` = %d LIMIT 1",
-                       intval($contact_id));
-               if(count($r)) {
-
-                       $filename = basename($r[0]['photo']);
-                       $img_str = fetch_url($r[0]['photo'],true);
-                       $img = new Photo($img_str);
-                       if($img->is_valid()) {
+               $filename = basename($contact['photo']);
+               $img_str = fetch_url($contact['photo'],true);
+               $img = new Photo($img_str);
+               if($img->is_valid()) {
 
-                               $img->scaleImageSquare(175);
+                       $img->scaleImageSquare(175);
                                        
-                               $hash = photo_new_resource();
+                       $hash = photo_new_resource();
 
-                               $r = $img->store($uid, $contact_id, $hash, $filename, t('Contact Photos'), 4 );
+                       $r = $img->store($uid, $contact_id, $hash, $filename, t('Contact Photos'), 4 );
 
-                               if($r === false)
-                                       $photo_failure = true;
-
-                               $img->scaleImage(80);
+                       if($r === false)
+                               $photo_failure = true;
 
-                               $r = $img->store($uid, $contact_id, $hash, $filename, t('Contact Photos'), 5 );
+                       $img->scaleImage(80);
 
-                               if($r === false)
-                                       $photo_failure = true;
+                       $r = $img->store($uid, $contact_id, $hash, $filename, t('Contact Photos'), 5 );
 
-                               $photo = $a->get_baseurl() . '/photo/' . $hash . '-4.jpg';
-                               $thumb = $a->get_baseurl() . '/photo/' . $hash . '-5.jpg';
-                       }
-                       else
+                       if($r === false)
                                $photo_failure = true;
+
+                       $photo = $a->get_baseurl() . '/photo/' . $hash . '-4.jpg';
+                       $thumb = $a->get_baseurl() . '/photo/' . $hash . '-5.jpg';
                }
                else
                        $photo_failure = true;
@@ -262,40 +263,89 @@ function dfrn_confirm_post(&$a,$handsfree = null) {
                        $thumb = $a->get_baseurl() . '/images/default-profile-sm.jpg';
                }
 
-               $new_relation = REL_VIP;
-               if(($relation == REL_FAN) || ($duplex))
-                       $new_relation = REL_BUD;
 
-               $r = q("UPDATE `contact` SET `photo` = '%s', 
-                       `thumb` = '%s', 
-                       `rel` = %d, 
-                       `name-date` = '%s', 
-                       `uri-date` = '%s', 
-                       `avatar-date` = '%s', 
-                       `blocked` = 0, 
-                       `pending` = 0,
-                       `duplex` = %d,
-                       `network` = 'dfrn' WHERE `id` = %d LIMIT 1
-               ",
-                       dbesc($photo),
-                       dbesc($thumb),
-                       intval($new_relation),
-                       dbesc(datetime_convert()),
-                       dbesc(datetime_convert()),
-                       dbesc(datetime_convert()),
-                       intval($duplex),
-                       intval($contact_id)
-               );
+               if($contact['network'] === 'dfrn') {
+
+                       $new_relation = REL_VIP;
+                       if(($relation == REL_FAN) || ($duplex))
+                               $new_relation = REL_BUD;
+
+                       $r = q("UPDATE `contact` SET `photo` = '%s', 
+                               `thumb` = '%s', 
+                               `rel` = %d, 
+                               `name-date` = '%s', 
+                               `uri-date` = '%s', 
+                               `avatar-date` = '%s', 
+                               `blocked` = 0, 
+                               `pending` = 0,
+                               `duplex` = %d,
+                               `network` = 'dfrn' WHERE `id` = %d LIMIT 1
+                       ",
+                               dbesc($photo),
+                               dbesc($thumb),
+                               intval($new_relation),
+                               dbesc(datetime_convert()),
+                               dbesc(datetime_convert()),
+                               dbesc(datetime_convert()),
+                               intval($duplex),
+                               intval($contact_id)
+                       );
+               }
+               else {  
+
+                       $notify = '';
+                       $poll   = '';
+
+                       // $contact['network'] !== 'dfrn'
+
+                       $arr = lrdd($contact['url']);
+                       if(count($arr)) {
+                               foreach($arr as $link) {
+                                       if($link['@attributes']['rel'] === 'salmon')
+                                               $notify = $link['@attributes']['href'];
+                                       if($link['@attributes']['rel'] === NAMESPACE_FEED)
+                                               $poll = $link['@attributes']['href'];
+                               }
+                       }
+
+                       $r = q("DELETE FROM `intro` WHERE `id` = %d AND `uid` = %d LIMIT 1",
+                               intval($intro_id),
+                               intval($uid)
+                       );
+
+                       $r = q("UPDATE `contact` SET `photo` = '%s', 
+                               `thumb` = '%s', 
+                               `name-date` = '%s', 
+                               `uri-date` = '%s', 
+                               `avatar-date` = '%s', 
+                               `notify` = '%s',
+                               `poll` = '%s',
+                               `blocked` = 0, 
+                               `pending` = 0
+                               WHERE `id` = %d LIMIT 1
+                       ",
+                               dbesc($photo),
+                               dbesc($thumb),
+                               dbesc(datetime_convert()),
+                               dbesc(datetime_convert()),
+                               dbesc(datetime_convert()),
+                               dbesc($notify),
+                               dbesc($poll),
+                               intval($contact_id)
+                       );                      
+               }
+
                if($r === false)
-                       notice( t('Unable to set contact photo.') . EOL);
+                               notice( t('Unable to set contact photo.') . EOL);
 
 
                // Let's send our user to the contact editor in case they want to
                // do anything special with this new friend.
+
                if($handsfree === null)
                        goaway($a->get_baseurl() . '/contacts/' . intval($contact_id));
                return;  //NOTREACHED
+
        }
 
 
@@ -480,7 +530,7 @@ function dfrn_confirm_post(&$a,$handsfree = null) {
                        intval($duplex),
                        intval($dfrn_record)
                );
-               if($r === false) { // indicates schema is messed up or total db failure
+               if($r === false) {    // indicates schema is messed up or total db failure
                        $message = t('Unable to update your contact profile details on our system');
                        xml_status(3,$message);
                }
index 517c91edaf7ff37318605f72e21f43be28369836..fc609ddc080ee4aad84af6105287a4183d0c14f1 100644 (file)
@@ -205,7 +205,7 @@ function dfrn_notify_post(&$a) {
                if($is_reply) {
                        if($feed->get_item_quantity() == 1) {
                                // remote reply to our post. Import and then notify everybody else.
-                               $datarray = get_atom_elements($item);
+                               $datarray = get_atom_elements($feed,$item);
                                $datarray['type'] = 'remote-comment';
                                $datarray['wall'] = 1;
                                $datarray['parent-uri'] = $parent_uri;
@@ -287,7 +287,7 @@ function dfrn_notify_post(&$a) {
                                        }
                                        continue;
                                }
-                               $datarray = get_atom_elements($item);
+                               $datarray = get_atom_elements($feed,$item);
                                $datarray['parent-uri'] = $parent_uri;
                                $datarray['uid'] = $importer['importer_uid'];
                                $datarray['contact-id'] = $importer['id'];
@@ -354,7 +354,7 @@ function dfrn_notify_post(&$a) {
                        }
 
 
-                       $datarray = get_atom_elements($item);
+                       $datarray = get_atom_elements($feed,$item);
                        $datarray['parent-uri'] = $item_id;
                        $datarray['uid'] = $importer['importer_uid'];
                        $datarray['contact-id'] = $importer['id'];
index 97a82a705c8a5ae12d5a1cec873ab1590f38f04c..5958a5905052d588b1e417222c38ee010be590c8 100644 (file)
@@ -200,7 +200,7 @@ function network_content(&$a, $update = 0) {
                                        $template = $wallwall;
                                        $commentww = 'ww';      
                                }
-                               if($item['type'] === 'remote' && ($item['owner-link'] != $item['author-link'])) {
+                               if(($item['type'] === 'remote') && (strlen($item['owner-link'])) && ($item['owner-link'] != $item['author-link'])) {
                                        // Could be anybody. 
                                        $owner_url = $item['owner-link'];
                                        $owner_photo = $item['owner-avatar'];
index d09ec5edeb24b461c607298ede82896e4b6fd447..b4116bbe3d8000d198dc808ca01bce0ed39600ff 100644 (file)
@@ -71,7 +71,7 @@ function notifications_content(&$a) {
                '$hide_text' => ((strlen($sql_extra)) ? t('Show Ignored Requests') : t('Hide Ignored Requests'))
        )); 
 
-       $r = q("SELECT `intro`.`id` AS `intro-id`, `intro`.*, `contact`.* 
+       $r = q("SELECT `intro`.`id` AS `intro_id`, `intro`.*, `contact`.* 
                FROM `intro` LEFT JOIN `contact` ON `intro`.`contact-id` = `contact`.`id`
                WHERE `intro`.`uid` = %d $sql_extra AND `intro`.`blocked` = 0 ",
                        intval($_SESSION['uid']));
@@ -83,15 +83,36 @@ function notifications_content(&$a) {
 
                foreach($r as $rr) {
 
+                       $friend_selected = (($rr['network'] === 'dfrn') ? ' checked="checked" ' : ' disabled ');
+                       $fan_selected = (($rr['network'] === 'stat') ? ' checked="checked" disabled ' : '');
+                       $dfrn_tpl = load_view_file('view/netfriend.tpl');
+
+                       $knowyou   = '';
+                       $dfrn_text = '';
+                                               
+                       if($rr['network'] === 'dfrn') {
+                               $knowyou = t('Claims to be known to you: ') . (($rr['knowyou']) ? t('yes') : t('no'));
+
+                               $dfrn_text = replace_macros($dfrn_tpl,array(
+                                       '$intro_id' => $rr['intro_id'],
+                                       '$friend_selected' => $friend_selected,
+                                       '$fan_selected' => $fan_selected,
+                               ));
+                       }                       
+
+
+
                        $o .= replace_macros($tpl,array(
-                               '$intro_id' => $rr['intro-id'],
-                               '$dfrn-id' => $rr['issued-id'],
+                               '$notify_type' => (($rr['network'] === 'dfrn') ? t('Friend/Connect Request') : t('New Follower')),
+                               '$dfrn_text' => $dfrn_text,     
+                               '$dfrn_id' => $rr['issued-id'],
                                '$uid' => $_SESSION['uid'],
-                               '$contact-id' => $rr['contact-id'],
+                               '$intro_id' => $rr['intro_id'],
+                               '$contact_id' => $rr['contact-id'],
                                '$photo' => ((x($rr,'photo')) ? $rr['photo'] : "images/default-profile.jpg"),
                                '$fullname' => $rr['name'],
-                               '$knowyou' => (($rr['knowyou']) ? t('yes') : t('no')),
                                '$url' => $rr['url'],
+                               '$knowyou' => $knowyou,
                                '$note' => $rr['note']
                        ));
                }
index 30e87f243fd436779c1d165add5cfdf66014685b..74377f9e941a70ba8afbda205b3089732955727a 100644 (file)
@@ -195,14 +195,16 @@ function salmon_post(&$a) {
        *
        */
 
-       $r = q("SELECT * FROM `contact` WHERE `network` = 'stat' AND `lrdd` = '%s' AND `uid` = %d LIMIT 1",
+       $r = q("SELECT * FROM `contact` WHERE `network` = 'stat' AND ( `url` = '%s' OR `lrdd` = '%s') AND `uid` = %d 
+               AND `readonly` = 0 LIMIT 1",
+               dbesc($author_link),
                dbesc($author_link),
                intval($importer['uid'])
        );
        if(! count($r)) {
                if($debugging)
                        file_put_contents('salmon.out',"\n" . 'Author unknown to us.' . "\n", FILE_APPEND);
-               salmon_return(500);
+
        }       
 
        require_once('include/items.php');
@@ -212,7 +214,9 @@ function salmon_post(&$a) {
 
        $hub = '';
 
-       consume_feed($feedxml,$importer,$r[0],$hub);
+       // consume_feed will only accept a follow activity from this person if there is no contact record.
+
+       consume_feed($feedxml,$importer,((count($r)) ? $r[0] : null),$hub);
 
        salmon_return(200);
 }
index 7ad97dfd2c8eb7376fa9f94a4dda70254080dadc..b5f2dcfea00769b513c89d312f16139fb1d5ad2d 100644 (file)
@@ -50,7 +50,7 @@ function contact_select($selname, $selclass, $preselected = false, $size = 4, $p
 
 
        $r = q("SELECT `id`, `name`, `url` FROM `contact` 
-               WHERE `uid` = %d AND `self` = 0 AND `blocked` = 0 AND `pending` = 0 
+               WHERE `uid` = %d AND `self` = 0 AND `blocked` = 0 AND `pending` = 0 AND `network` = 'dfrn' 
                $sql_extra
                ORDER BY `name` ASC ",
                $_SESSION['uid']
index a56c7742d02f85be22ceb1e27afe7ab1fed7d221..30198beb850407026130112d71b0796b4bac555e 100644 (file)
@@ -1,12 +1,12 @@
 
-<div class="intro-wrapper" id="intro-$contact-id" >
+<div class="intro-wrapper" id="intro-$contact_id" >
 
-<p class="intro-desc">Notification type: Friend/Connect Request</p>
-<div class="intro-fullname" id="intro-fullname-$contact-id" >$fullname</div>
-<a class="intro-url-link" id="intro-url-link-$contact-id" href="$url" ><img id="photo-$contact-id" class="intro-photo" src="$photo" width="175" height=175" name="$fullname" alt="fullname" /></a>
-<div class="intro-knowyou">Presumably known to you? <strong>$knowyou</strong></div>
-<div class="intro-note" id="intro-note-$contact-id">$note</div>
-<div class="intro-wrapper-end" id="intro-wrapper-end-$contact-id"></div>
+<p class="intro-desc">Notification type: $notify_type</p>
+<div class="intro-fullname" id="intro-fullname-$contact_id" >$fullname</div>
+<a class="intro-url-link" id="intro-url-link-$contact_id" href="$url" ><img id="photo-$contact_id" class="intro-photo" src="$photo" width="175" height=175" name="$fullname" alt="fullname" /></a>
+<div class="intro-knowyou">$knowyou</div>
+<div class="intro-note" id="intro-note-$contact_id">$note</div>
+<div class="intro-wrapper-end" id="intro-wrapper-end-$contact_id"></div>
 <form class="intro-form" action="notifications/$intro_id" method="post">
 <input class="intro-submit-ignore" type="submit" name="submit" value="Ignore" />
 <input class="intro-submit-discard" type="submit" name="submit" value="Discard" />
 <div class="intro-form-end"></div>
 
 <form class="intro-approve-form" action="dfrn_confirm" method="post">
-<input type="hidden" name="dfrn_id" value="$dfrn-id" >
+<input type="hidden" name="dfrn_id" value="$dfrn_id" >
 <input type="hidden" name="intro_id" value="$intro_id" >
+<input type="hidden" name="contact_id" value="$contact_id" >
 
-<div class="intro-approve-as-friend-desc">Approve as: </div>
-
-<div class="intro-approve-as-friend-wrapper">
-       <label class="intro-approve-as-friend-label" for="intro-approve-as-friend-$intro_id">Friend</label>
-       <input type="radio" name="duplex" id="intro-approve-as-friend-$intro_id" class="intro-approve-as-friend" checked="checked" value="1" />
-       <div class="intro-approve-friend-break" ></div> 
-</div>
-<div class="intro-approve-as-friend-end"></div>
-<div class="intro-approve-as-fan-wrapper">
-       <label class="intro-approve-as-fan-label" for="intro-approve-as-fan-$intro_id">Fan/Admirer</label>
-       <input type="radio" name="duplex" id="intro-approve-as-fan-$intro_id" class="intro-approve-as-fan" $fan_selected value="0"  />
-       <div class="intro-approve-fan-break"></div>
-</div>
-<div class="intro-approve-as-end"></div>
+$dfrn_text
 
 <input class="intro-submit-approve" type="submit" name="submit" value="Approve" />
 </form>
diff --git a/view/magicsig.tpl b/view/magicsig.tpl
new file mode 100644 (file)
index 0000000..46b4d4e
--- /dev/null
@@ -0,0 +1,9 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<me:env xmlns:me='http://salmon-protocol.org/ns/magic-env'>
+<me:data type='application/atom+xml'>
+$data
+</me:data>
+<me:encoding>$encoding</me:encoding>
+<me:alg>$algorithm</me:/alg>
+<me:sig keyash="$keyhash">$signature</me:sig>
+</me:env>
diff --git a/view/netfriend.tpl b/view/netfriend.tpl
new file mode 100644 (file)
index 0000000..b041ec4
--- /dev/null
@@ -0,0 +1,14 @@
+<div class="intro-approve-as-friend-desc">Approve as: </div>
+
+<div class="intro-approve-as-friend-wrapper">
+       <label class="intro-approve-as-friend-label" for="intro-approve-as-friend-$intro_id">Friend</label>
+       <input type="radio" name="duplex" id="intro-approve-as-friend-$intro_id" class="intro-approve-as-friend" $friend_selected value="1" />
+       <div class="intro-approve-friend-break" ></div> 
+</div>
+<div class="intro-approve-as-friend-end"></div>
+<div class="intro-approve-as-fan-wrapper">
+       <label class="intro-approve-as-fan-label" for="intro-approve-as-fan-$intro_id">Fan/Admirer</label>
+       <input type="radio" name="duplex" id="intro-approve-as-fan-$intro_id" class="intro-approve-as-fan" $fan_selected value="0"  />
+       <div class="intro-approve-fan-break"></div>
+</div>
+<div class="intro-approve-as-end"></div>
index 32d8eeba0dc6db211cb860fea803a452dfb915ae..ca4891a7673284afae10c645e92df56d2c44b2c6 100644 (file)
@@ -527,6 +527,10 @@ input#dfrn-url {
        clear: both;
 }
 
+.intro-wrapper {
+       margin-top: 20px;
+}
+
 .intro-fullname {
        font-size: 1.1em;
        font-weight: bold;
@@ -534,6 +538,7 @@ input#dfrn-url {
 }
 .intro-desc {
        margin-bottom: 20px;
+       font-weight: bold;
 }
 
 .intro-note {
@@ -556,6 +561,10 @@ input#dfrn-url {
 .intro-submit-approve, .intro-submit-ignore {
        margin-right: 20px;
 }
+.intro-submit-approve {
+       margin-top: 15px;
+}
+
 .intro-approve-as-friend-label, .intro-approve-as-fan-label {
        float: left;
        width: 100px;