From d1d794f1ab4b30a2bbf7d52933b7c37435bf6826 Mon Sep 17 00:00:00 2001 From: Michael Vogel Date: Sun, 15 Feb 2015 10:52:45 +0100 Subject: [PATCH] The global contacts now contain a "generation" value that defines how we know this contact --- boot.php | 2 +- include/dbstructure.php | 1 + include/diaspora.php | 2 +- include/items.php | 67 +++++++++++++++++++++--- include/socgraph.php | 110 +++++++++++++++++++++++++++++++++++----- mod/poco.php | 22 ++++++-- update.php | 2 +- 7 files changed, 179 insertions(+), 27 deletions(-) diff --git a/boot.php b/boot.php index c136dc5744..0ab171d5f3 100644 --- a/boot.php +++ b/boot.php @@ -18,7 +18,7 @@ define ( 'FRIENDICA_PLATFORM', 'Friendica'); define ( 'FRIENDICA_CODENAME', 'Ginger'); define ( 'FRIENDICA_VERSION', '3.3.3-RC' ); define ( 'DFRN_PROTOCOL_VERSION', '2.23' ); -define ( 'DB_UPDATE_VERSION', 1179 ); +define ( 'DB_UPDATE_VERSION', 1180 ); define ( 'EOL', "
\r\n" ); define ( 'ATOM_TIME', 'Y-m-d\TH:i:s\Z' ); diff --git a/include/dbstructure.php b/include/dbstructure.php index adb826c8b4..0ee28e0a67 100644 --- a/include/dbstructure.php +++ b/include/dbstructure.php @@ -626,6 +626,7 @@ function db_definition() { "keywords" => array("type" => "text", "not null" => "1"), "gender" => array("type" => "varchar(32)", "not null" => "1", "default" => ""), "network" => array("type" => "varchar(255)", "not null" => "1", "default" => ""), + "generation" => array("type" => "tinyint(3)", "not null" => "1", "default" => "0"), ), "indexes" => array( "PRIMARY" => array("id"), diff --git a/include/diaspora.php b/include/diaspora.php index f7537ef633..a0d1fcd751 100755 --- a/include/diaspora.php +++ b/include/diaspora.php @@ -2398,7 +2398,7 @@ function diaspora_profile($importer,$xml,$msg) { if (unxmlify($xml->searchable) == "true") { require_once('include/socgraph.php'); poco_check($contact['url'], $name, NETWORK_DIASPORA, $images[0], $about, $location, $gender, $keywords, "", - datetime_convert(), $contact['id'], $importer['uid']); + datetime_convert(), 2, $contact['id'], $importer['uid']); } $profileurl = ""; diff --git a/include/items.php b/include/items.php index e8fc739cd0..e786eafd98 100644 --- a/include/items.php +++ b/include/items.php @@ -1377,15 +1377,51 @@ function item_store($arr,$force_parent = false, $notify = false, $dontcache = fa logger('item_store: created item ' . $current_post); // Add every contact to the global contact table - // Contacts from the statusnet connector are also added since you could add them in OStatus as well. - if (!$arr['private'] AND in_array($arr["network"], - array(NETWORK_DFRN, NETWORK_DIASPORA, NETWORK_OSTATUS, NETWORK_STATUSNET, ""))) { - poco_check($arr["author-link"], $arr["author-name"], $arr["network"], $arr["author-avatar"], "", "", "", "", "", $arr["received"], $arr["contact-id"], $arr["uid"]); + poco_store($arr); + +/* + // Is it a global copy? + $store_gcontact = ($arr["uid"] == 0); + + // Is it a comment on a global copy? + if (!$store_gcontact AND ($arr["uri"] != $arr["parent-uri"])) { + $q = q("SELECT `id` FROM `item` WHERE `uri`='%s' AND `uid` = 0", + $arr["parent-uri"]); + $store_gcontact = count($q); + } + + // This check for private and network is maybe superflous + if ($store_gcontact AND !$arr['private'] AND in_array($arr["network"], + array(NETWORK_DFRN, NETWORK_DIASPORA, NETWORK_OSTATUS, ""))) { + + // "3" means: We don't know this contact directly (Maybe a reshared item) + $generation = 3; + $network = ""; + + // Is it a user from our server? + $q = q("SELECT `id` FROM `contact` WHERE `self` AND `nurl` = '%s' LIMIT 1", + dbesc(normalise_link($arr["author-link"]))); + if (count($q)) { + $generation = 1; + $network = NETWORK_DFRN; + } else { // Is it a contact from a user on our server? + $q = q("SELECT `network` FROM `contact` WHERE `uid` != 0 AND `network` != '' + AND (`nurl` = '%s' OR `alias` IN ('%s', '%s')) LIMIT 1", + dbesc(normalise_link($arr["author-link"])), + dbesc(normalise_link($arr["author-link"])), + dbesc($arr["author-link"])); + if (count($q)) { + $generation = 2; + $network = $q[0]["network"]; + } + } + + poco_check($arr["author-link"], $arr["author-name"], $network, $arr["author-avatar"], "", "", "", "", "", $arr["received"], $generation, $arr["contact-id"], $arr["uid"]); // Maybe its a body with a shared item? Then extract a global contact from it. poco_contact_from_body($arr["body"], $arr["received"], $arr["contact-id"], $arr["uid"]); } - +*/ // Set "success_update" to the date of the last time we heard from this contact // This can be used to filter for inactive contacts and poco. // Only do this for public postings to avoid privacy problems, since poco data is public. @@ -2078,6 +2114,7 @@ function consume_feed($xml,$importer,&$contact, &$hub, $datedir = 0, $pass = 0) $photo_timestamp = ''; $photo_url = ''; $birthday = ''; + $contact_updated = ''; $hubs = $feed->get_links('hub'); logger('consume_feed: hubs: ' . print_r($hubs,true), LOGGER_DATA); @@ -2113,6 +2150,9 @@ function consume_feed($xml,$importer,&$contact, &$hub, $datedir = 0, $pass = 0) if((is_array($contact)) && ($photo_timestamp) && (strlen($photo_url)) && ($photo_timestamp > $contact['avatar-date'])) { logger('consume_feed: Updating photo for '.$contact['name'].' from '.$photo_url.' uid: '.$contact['uid']); + + $contact_updated = $photo_timestamp; + require_once("include/Photo.php"); $photo_failure = false; $have_photo = false; @@ -2170,6 +2210,9 @@ 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'])) { + if ($name_updated > $contact_updated) + $contact_updated = $name_updated; + $r = q("select * from contact where uid = %d and id = %d limit 1", intval($contact['uid']), intval($contact['id']) @@ -2194,6 +2237,9 @@ function consume_feed($xml,$importer,&$contact, &$hub, $datedir = 0, $pass = 0) } } + if ($contact_updated AND $new_name AND $photo_url) + poco_check($contact['url'], $new_name, NETWORK_DFRN, $photo_url, "", "", "", "", "", $contact_updated, 2, $contact['id'], $contact['uid']); + if(strlen($birthday)) { if(substr($birthday,0,4) != $contact['bdyear']) { logger('consume_feed: updating birthday: ' . $birthday); @@ -2240,7 +2286,6 @@ function consume_feed($xml,$importer,&$contact, &$hub, $datedir = 0, $pass = 0) $contact['bdyear'] = substr($birthday,0,4); } - } $community_page = 0; @@ -2806,6 +2851,7 @@ function local_delivery($importer,$data) { $new_name = ''; $photo_timestamp = ''; $photo_url = ''; + $contact_updated = ''; $rawtags = $feed->get_feed_tags( NAMESPACE_DFRN, 'owner'); @@ -2834,6 +2880,9 @@ function local_delivery($importer,$data) { } if(($photo_timestamp) && (strlen($photo_url)) && ($photo_timestamp > $importer['avatar-date'])) { + + $contact_updated = $photo_timestamp; + logger('local_delivery: Updating photo for ' . $importer['name']); require_once("include/Photo.php"); $photo_failure = false; @@ -2892,6 +2941,9 @@ function local_delivery($importer,$data) { } if(($name_updated) && (strlen($new_name)) && ($name_updated > $importer['name-date'])) { + if ($name_updated > $contact_updated) + $contact_updated = $name_updated; + $r = q("select * from contact where uid = %d and id = %d limit 1", intval($importer['importer_uid']), intval($importer['id']) @@ -2916,7 +2968,8 @@ function local_delivery($importer,$data) { } } - + if ($contact_updated AND $new_name AND $photo_url) + poco_check($importer['url'], $new_name, NETWORK_DFRN, $photo_url, "", "", "", "", "", $contact_updated, 2, $importer['id'], $importer['importer_uid']); // Currently unsupported - needs a lot of work $reloc = $feed->get_feed_tags( NAMESPACE_DFRN, 'relocate' ); diff --git a/include/socgraph.php b/include/socgraph.php index 2738f8a70f..ab348997c8 100644 --- a/include/socgraph.php +++ b/include/socgraph.php @@ -42,7 +42,7 @@ function poco_load($cid,$uid = 0,$zcid = 0,$url = null) { if(! $url) return; - $url = $url . (($uid) ? '/@me/@all?fields=displayName,urls,photos,updated,network,aboutMe,currentLocation,tags,gender' : '?fields=displayName,urls,photos,updated,network,aboutMe,currentLocation,tags,gender') ; + $url = $url . (($uid) ? '/@me/@all?fields=displayName,urls,photos,updated,network,aboutMe,currentLocation,tags,gender,generation' : '?fields=displayName,urls,photos,updated,network,aboutMe,currentLocation,tags,gender,generation') ; logger('poco_load: ' . $url, LOGGER_DEBUG); @@ -76,6 +76,10 @@ function poco_load($cid,$uid = 0,$zcid = 0,$url = null) { $about = ''; $keywords = ''; $gender = ''; + $generation = 0; + + if ($uid == 0) + $network = NETWORK_DFRN; $name = $entry->displayName; @@ -115,11 +119,14 @@ function poco_load($cid,$uid = 0,$zcid = 0,$url = null) { if(isset($entry->gender)) $gender = $entry->gender; + if(isset($entry->generation) AND ($entry->generation > 0)) + $generation = ++$entry->generation; + if(isset($entry->tags)) foreach($entry->tags as $tag) $keywords = implode(", ", $tag); - poco_check($profile_url, $name, $network, $profile_photo, $about, $location, $gender, $keywords, $connect_url, $updated, $cid, $uid, $zcid); + poco_check($profile_url, $name, $network, $profile_photo, $about, $location, $gender, $keywords, $connect_url, $updated, $generation, $cid, $uid, $zcid); // Update the Friendica contacts. Diaspora is doing it via a message. (See include/diaspora.php) if (($location != "") OR ($about != "") OR ($keywords != "") OR ($gender != "")) @@ -142,16 +149,40 @@ function poco_load($cid,$uid = 0,$zcid = 0,$url = null) { } -function poco_check($profile_url, $name, $network, $profile_photo, $about, $location, $gender, $keywords, $connect_url, $updated, $cid = 0, $uid = 0, $zcid = 0) { +function poco_check($profile_url, $name, $network, $profile_photo, $about, $location, $gender, $keywords, $connect_url, $updated, $generation, $cid = 0, $uid = 0, $zcid = 0) { + + // Generation: + // 0: No definition + // 1: Profiles on this server + // 2: Contacts of profiles on this server + // 3: Contacts of contacts of profiles on this server + // 4: ... + $gcid = ""; if ($profile_url == "") return $gcid; + $r = q("SELECT `network` FROM `contact` WHERE `nurl` = '%s' AND `network` != '' LIMIT 1", + dbesc(normalise_link($profile_url)) + ); + if(count($r)) + $network = $r[0]["network"]; + + if ($network == "") { + $r = q("SELECT `network`, `url` FROM `contact` WHERE `alias` IN ('%s', '%s') AND `network` != '' LIMIT 1", + dbesc($profile_url), dbesc(normalise_link($profile_url)) + ); + if(count($r)) { + $network = $r[0]["network"]; + $profile_url = $r[0]["url"]; + } + } + $x = q("SELECT * FROM `gcontact` WHERE `nurl` = '%s' LIMIT 1", dbesc(normalise_link($profile_url)) ); - if(count($x)) + if(count($x) AND ($network == "")) $network = $x[0]["network"]; if (($network == "") OR ($name == "") OR ($profile_photo == "")) { @@ -176,7 +207,7 @@ function poco_check($profile_url, $name, $network, $profile_photo, $about, $loca if (!in_array($network, array(NETWORK_DFRN, NETWORK_OSTATUS, NETWORK_DIASPORA, NETWORK_STATUSNET))) return $gcid; - logger("profile-check URL: ".$profile_url." name: ".$name." avatar: ".$profile_photo, LOGGER_DEBUG); + logger("profile-check generation: ".$generation." Network: ".$network." URL: ".$profile_url." name: ".$name." avatar: ".$profile_photo, LOGGER_DEBUG); if(count($x)) { $gcid = $x[0]['id']; @@ -193,10 +224,13 @@ function poco_check($profile_url, $name, $network, $profile_photo, $about, $loca if (($keywords == "") AND ($x[0]['keywords'] != "")) $keywords = $x[0]['keywords']; + if (($generation == 0) AND ($x[0]['generation'] > 0)) + $generation = $x[0]['generation']; + if($x[0]['name'] != $name || $x[0]['photo'] != $profile_photo || $x[0]['updated'] < $updated) { - q("update gcontact set `name` = '%s', `network` = '%s', `photo` = '%s', `connect` = '%s', `url` = '%s', - `updated` = '%s', `location` = '%s', `about` = '%s', `keywords` = '%s', `gender` = '%s' - where `nurl` = '%s'", + q("UPDATE `gcontact` SET `name` = '%s', `network` = '%s', `photo` = '%s', `connect` = '%s', `url` = '%s', + `updated` = '%s', `location` = '%s', `about` = '%s', `keywords` = '%s', `gender` = '%s', `generation` = %d + WHERE (`generation` >= %d OR `generation` = 0) AND `nurl` = '%s'", dbesc($name), dbesc($network), dbesc($profile_photo), @@ -207,12 +241,14 @@ function poco_check($profile_url, $name, $network, $profile_photo, $about, $loca dbesc($about), dbesc($keywords), dbesc($gender), + intval($generation), + intval($generation), dbesc(normalise_link($profile_url)) ); } } else { - q("insert into `gcontact` (`name`,`network`, `url`,`nurl`,`photo`,`connect`, `updated`, `location`, `about`, `keywords`, `gender`) - values ('%s', '%s', '%s', '%s', '%s','%s', '%s', '%s', '%s', '%s', '%s')", + q("INSERT INTO `gcontact` (`name`,`network`, `url`,`nurl`,`photo`,`connect`, `updated`, `location`, `about`, `keywords`, `gender`, `generation`) + VALUES ('%s', '%s', '%s', '%s', '%s','%s', '%s', '%s', '%s', '%s', '%s', %d)", dbesc($name), dbesc($network), dbesc($profile_url), @@ -223,7 +259,8 @@ function poco_check($profile_url, $name, $network, $profile_photo, $about, $loca dbesc($location), dbesc($about), dbesc($keywords), - dbesc($gender) + dbesc($gender), + intval($generation) ); $x = q("SELECT * FROM `gcontact` WHERE `nurl` = '%s' LIMIT 1", dbesc(normalise_link($profile_url)) @@ -290,7 +327,56 @@ function sub_poco_from_share($share, $created, $cid, $uid) { return; logger("prepare poco_check for profile ".$profile, LOGGER_DEBUG); - poco_check($profile, "", "", "", "", "", "", "", "", $created, $cid, $uid); + poco_check($profile, "", "", "", "", "", "", "", "", $created, 3, $cid, $uid); +} + +function poco_store($item) { + + // Isn't it public? + if (!$item['private']) + return; + + // Or is it from a network where we don't store the global contacts? + if (!in_array($item["network"], array(NETWORK_DFRN, NETWORK_DIASPORA, NETWORK_OSTATUS, ""))) + return; + + // Is it a global copy? + $store_gcontact = ($item["uid"] == 0); + + // Is it a comment on a global copy? + if (!$store_gcontact AND ($item["uri"] != $item["parent-uri"])) { + $q = q("SELECT `id` FROM `item` WHERE `uri`='%s' AND `uid` = 0", $item["parent-uri"]); + $store_gcontact = count($q); + } + + if (!$store_gcontact) + return; + + // "3" means: We don't know this contact directly (Maybe a reshared item) + $generation = 3; + $network = ""; + + // Is it a user from our server? + $q = q("SELECT `id` FROM `contact` WHERE `self` AND `nurl` = '%s' LIMIT 1", + dbesc(normalise_link($item["author-link"]))); + if (count($q)) { + $generation = 1; + $network = NETWORK_DFRN; + } else { // Is it a contact from a user on our server? + $q = q("SELECT `network` FROM `contact` WHERE `uid` != 0 AND `network` != '' + AND (`nurl` = '%s' OR `alias` IN ('%s', '%s')) LIMIT 1", + dbesc(normalise_link($item["author-link"])), + dbesc(normalise_link($item["author-link"])), + dbesc($item["author-link"])); + if (count($q)) { + $generation = 2; + $network = $q[0]["network"]; + } + } + poco_check($item["author-link"], $item["author-name"], $network, $item["author-avatar"], "", "", "", "", "", $item["received"], $generation, $item["contact-id"], $item["uid"]); + + // Maybe its a body with a shared item? Then extract a global contact from it. + poco_contact_from_body($item["body"], $item["received"], $item["contact-id"], $item["uid"]); } function count_common_friends($uid,$cid) { diff --git a/mod/poco.php b/mod/poco.php index 8eb45d2374..86b43d651d 100644 --- a/mod/poco.php +++ b/mod/poco.php @@ -135,9 +135,9 @@ function poco_init(&$a) { if(x($_GET,'updatedSince') AND !$global) $ret['updatedSince'] = false; - $ret['startIndex'] = (string) $startIndex; - $ret['itemsPerPage'] = (string) $itemsPerPage; - $ret['totalResults'] = (string) $totalResults; + $ret['startIndex'] = (int) $startIndex; + $ret['itemsPerPage'] = (int) $itemsPerPage; + $ret['totalResults'] = (int) $totalResults; $ret['entry'] = array(); @@ -153,7 +153,8 @@ function poco_init(&$a) { 'network' => false, 'gender' => false, 'tags' => false, - 'address' => false + 'address' => false, + 'generation' => false ); if((! x($_GET,'fields')) || ($_GET['fields'] === '@all')) @@ -168,6 +169,15 @@ function poco_init(&$a) { if(is_array($r)) { if(count($r)) { foreach($r as $rr) { + if (!isset($rr['generation'])) { + if ($global) + $rr['generation'] = 3; + elseif ($system_mode) + $rr['generation'] = 1; + else + $rr['generation'] = 2; + } + if (($rr['about'] == "") AND isset($rr['pabout'])) $rr['about'] = $rr['pabout']; @@ -198,7 +208,7 @@ function poco_init(&$a) { $entry = array(); if($fields_ret['id']) - $entry['id'] = $rr['id']; + $entry['id'] = (int)$rr['id']; if($fields_ret['displayName']) $entry['displayName'] = $rr['name']; if($fields_ret['aboutMe']) @@ -207,6 +217,8 @@ function poco_init(&$a) { $entry['currentLocation'] = $rr['location']; if($fields_ret['gender']) $entry['gender'] = $rr['gender']; + if($fields_ret['generation']) + $entry['generation'] = (int)$rr['generation']; if($fields_ret['urls']) { $entry['urls'] = array(array('value' => $rr['url'], 'type' => 'profile')); if($rr['addr'] && ($rr['network'] !== NETWORK_MAIL)) diff --git a/update.php b/update.php index 53cd0e305c..954993a70a 100644 --- a/update.php +++ b/update.php @@ -1,6 +1,6 @@