X-Git-Url: https://git.mxchange.org/?a=blobdiff_plain;f=include%2Fdiaspora.php;h=3145c52ea3fbb62242c2254aa1728aa547db5077;hb=2e8caf7f27197be5f12ea22f4a5e9aae2bb1ee89;hp=feb57a04045ec5c0a4630d5a1e561a6c0b71129e;hpb=84189ac775b3e1bc36d9e9d8945624c1bca7fb55;p=friendica.git diff --git a/include/diaspora.php b/include/diaspora.php old mode 100755 new mode 100644 index feb57a0404..3145c52ea3 --- a/include/diaspora.php +++ b/include/diaspora.php @@ -1,11 +1,18 @@ 0, "page-flags" => PAGE_FREELOVE); + $result = diaspora_dispatch($importer,$msg); + logger("Dispatcher reported ".$result, LOGGER_DEBUG); + + // Now distribute it to the followers $r = q("SELECT `user`.* FROM `user` WHERE `user`.`uid` IN - ( SELECT `contact`.`uid` FROM `contact` WHERE `contact`.`network` = '%s' AND `contact`.`addr` = '%s' ) - AND `account_expired` = 0 AND `account_removed` = 0 ", + ( SELECT `contact`.`uid` FROM `contact` WHERE `contact`.`network` = '%s' AND `contact`.`addr` = '%s' ) + AND `account_expired` = 0 AND `account_removed` = 0 ", dbesc(NETWORK_DIASPORA), dbesc($msg['author']) ); @@ -28,7 +41,7 @@ function diaspora_dispatch_public($msg) { } } else - logger('diaspora_public: no subscribers'); + logger('diaspora_public: no subscribers for '.$msg["author"].' '.print_r($msg, true)); } @@ -262,7 +275,7 @@ function diaspora_pubmsg_build($msg,$user,$contact,$prvkey,$pubkey) { logger('diaspora_pubmsg_build: ' . $msg, LOGGER_DATA); - + $handle = $user['nickname'] . '@' . substr($a->get_baseurl(), strpos($a->get_baseurl(),'://') + 3); // $b64_data = base64_encode($msg); @@ -276,7 +289,7 @@ function diaspora_pubmsg_build($msg,$user,$contact,$prvkey,$pubkey) { $encoding = 'base64url'; $alg = 'RSA-SHA256'; - $signable_data = $data . '.' . base64url_encode($type) . '.' + $signable_data = $data . '.' . base64url_encode($type) . '.' . base64url_encode($encoding) . '.' . base64url_encode($alg) ; $signature = rsa_sign($signable_data,$prvkey); @@ -329,7 +342,7 @@ function diaspora_msg_build($msg,$user,$contact,$prvkey,$pubkey,$public = false) $b_outer_aes_key = base64_encode($outer_aes_key); $outer_iv = random_string(16); $b_outer_iv = base64_encode($outer_iv); - + $handle = $user['nickname'] . '@' . substr($a->get_baseurl(), strpos($a->get_baseurl(),'://') + 3); $padded_data = pkcs5_pad($msg,16); @@ -345,7 +358,7 @@ function diaspora_msg_build($msg,$user,$contact,$prvkey,$pubkey,$public = false) $encoding = 'base64url'; $alg = 'RSA-SHA256'; - $signable_data = $data . '.' . base64url_encode($type) . '.' + $signable_data = $data . '.' . base64url_encode($type) . '.' . base64url_encode($encoding) . '.' . base64url_encode($alg) ; $signature = rsa_sign($signable_data,$prvkey); @@ -425,7 +438,7 @@ function diaspora_decode($importer,$xml) { else { $encrypted_header = json_decode(base64_decode($children->encrypted_header)); - + $encrypted_aes_key_bundle = base64_decode($encrypted_header->aes_key); $ciphertext = base64_decode($encrypted_header->ciphertext); @@ -538,7 +551,7 @@ function diaspora_decode($importer,$xml) { // This will also convert diaspora public key from pkcs#1 to pkcs#8 logger('mod-diaspora: Fetching key for ' . $author_link ); - $key = get_diaspora_key($author_link); + $key = get_diaspora_key($author_link); if(! $key) { logger('mod-diaspora: Could not retrieve author key.'); @@ -576,7 +589,7 @@ function diaspora_request($importer,$xml) { // perhaps we were already sharing with this person. Now they're sharing with us. // That makes us friends. - if($contact['rel'] == CONTACT_IS_FOLLOWER && $importer['page-flags'] != PAGE_COMMUNITY) { + if($contact['rel'] == CONTACT_IS_FOLLOWER && !in_array($importer['page-flags'], array(PAGE_COMMUNITY, PAGE_SOAPBOX))) { q("UPDATE `contact` SET `rel` = %d, `writable` = 1 WHERE `id` = %d AND `uid` = %d", intval(CONTACT_IS_FRIEND), intval($contact['id']), @@ -589,7 +602,7 @@ function diaspora_request($importer,$xml) { intval($importer['uid']) ); - if((count($r)) && (! $r[0]['hide-friends']) && (! $contact['hidden'])) { + if((count($r)) && (!$r[0]['hide-friends']) && (!$contact['hidden']) && intval(get_pconfig($importer['uid'],'system','post_newfriend'))) { require_once('include/items.php'); $self = q("SELECT * FROM `contact` WHERE `self` = 1 AND `uid` = %d LIMIT 1", @@ -601,7 +614,7 @@ function diaspora_request($importer,$xml) { if(count($self) && $contact['rel'] == CONTACT_IS_FOLLOWER) { $arr = array(); - $arr['uri'] = $arr['parent-uri'] = item_new_uri($a->get_hostname(), $importer['uid']); + $arr['uri'] = $arr['parent-uri'] = item_new_uri($a->get_hostname(), $importer['uid']); $arr['uid'] = $importer['uid']; $arr['contact-id'] = $self[0]['id']; $arr['wall'] = 1; @@ -633,7 +646,7 @@ function diaspora_request($importer,$xml) { $i = item_store($arr); if($i) - proc_run('php',"include/notifier.php","activity","$i"); + proc_run('php',"include/notifier.php","activity","$i"); } @@ -713,7 +726,7 @@ function diaspora_request($importer,$xml) { $photos = import_profile_photo($contact_record['photo'],$importer['uid'],$contact_record['id']); - // technically they are sharing with us (CONTACT_IS_SHARING), + // technically they are sharing with us (CONTACT_IS_SHARING), // but if our page-type is PAGE_COMMUNITY or PAGE_SOAPBOX // we are going to change the relationship and make them a follower. @@ -722,16 +735,17 @@ function diaspora_request($importer,$xml) { else $new_relation = CONTACT_IS_FOLLOWER; - $r = q("UPDATE `contact` SET - `photo` = '%s', + $r = q("UPDATE `contact` SET + `photo` = '%s', `thumb` = '%s', - `micro` = '%s', - `rel` = %d, - `name-date` = '%s', - `uri-date` = '%s', - `avatar-date` = '%s', - `blocked` = 0, - `pending` = 0 + `micro` = '%s', + `rel` = %d, + `name-date` = '%s', + `uri-date` = '%s', + `avatar-date` = '%s', + `blocked` = 0, + `pending` = 0, + `writable` = 1 WHERE `id` = %d ", dbesc($photos[0]), @@ -752,12 +766,12 @@ function diaspora_request($importer,$xml) { return; } -function diaspora_post_allow($importer,$contact) { +function diaspora_post_allow($importer,$contact, $is_comment = false) { // perhaps we were already sharing with this person. Now they're sharing with us. // That makes us friends. // Normally this should have handled by getting a request - but this could get lost - if($contact['rel'] == CONTACT_IS_FOLLOWER && $importer['page-flags'] != PAGE_COMMUNITY) { + if($contact['rel'] == CONTACT_IS_FOLLOWER && !in_array($importer['page-flags'], array(PAGE_COMMUNITY, PAGE_SOAPBOX))) { q("UPDATE `contact` SET `rel` = %d, `writable` = 1 WHERE `id` = %d AND `uid` = %d", intval(CONTACT_IS_FRIEND), intval($contact['id']), @@ -772,11 +786,41 @@ function diaspora_post_allow($importer,$contact) { if($contact['rel'] == CONTACT_IS_SHARING || $contact['rel'] == CONTACT_IS_FRIEND) return true; if($contact['rel'] == CONTACT_IS_FOLLOWER) - if($importer['page-flags'] == PAGE_COMMUNITY) + if(($importer['page-flags'] == PAGE_COMMUNITY) OR $is_comment) return true; + + // Messages for the global users are always accepted + if ($importer['uid'] == 0) + return true; + return false; } +function diaspora_is_redmatrix($url) { + return(strstr($url, "/channel/")); +} + +function diaspora_plink($addr, $guid) { + $r = q("SELECT `url`, `nick`, `network` FROM `fcontact` WHERE `addr`='%s' LIMIT 1", $addr); + + // Fallback + if (!$r) + return 'https://'.substr($addr,strpos($addr,'@')+1).'/posts/'.$guid; + + // Friendica contacts are often detected as Diaspora contacts in the "fcontact" table + // So we try another way as well. + $s = q("SELECT `network` FROM `gcontact` WHERE `nurl`='%s' LIMIT 1", dbesc(normalise_link($r[0]["url"]))); + if ($s) + $r[0]["network"] = $s[0]["network"]; + + if ($r[0]["network"] == NETWORK_DFRN) + return(str_replace("/profile/".$r[0]["nick"]."/", "/display/".$guid, $r[0]["url"]."/")); + + if (diaspora_is_redmatrix($r[0]["url"])) + return $r[0]["url"]."/?f=&mid=".$guid; + + return 'https://'.substr($addr,strpos($addr,'@')+1).'/posts/'.$guid; +} function diaspora_post($importer,$xml,$msg) { @@ -790,35 +834,24 @@ function diaspora_post($importer,$xml,$msg) { } $contact = diaspora_get_contact_by_handle($importer['uid'],$diaspora_handle); - if(! $contact) - return; + if(! $contact) { + logger('diaspora_post: A Contact for handle '.$diaspora_handle.' and user '.$importer['uid'].' was not found'); + return 203; + } - if(! diaspora_post_allow($importer,$contact)) { + if(! diaspora_post_allow($importer,$contact, false)) { logger('diaspora_post: Ignoring this author.'); return 202; } $message_id = $diaspora_handle . ':' . $guid; - $r = q("SELECT `id` FROM `item` WHERE `uid` = %d AND `uri` = '%s' AND `guid` = '%s' LIMIT 1", + $r = q("SELECT `id` FROM `item` WHERE `uid` = %d AND `guid` = '%s' LIMIT 1", intval($importer['uid']), - dbesc($message_id), dbesc($guid) ); if(count($r)) { logger('diaspora_post: message exists: ' . $guid); - return; - } - - // allocate a guid on our system - we aren't fixing any collisions. - // we're ignoring them - - $g = q("select * from guid where guid = '%s' limit 1", - dbesc($guid) - ); - if(! count($g)) { - q("insert into guid ( guid ) values ( '%s' )", - dbesc($guid) - ); + return 208; } $created = unxmlify($xml->created_at); @@ -826,38 +859,21 @@ function diaspora_post($importer,$xml,$msg) { $body = diaspora2bb($xml->raw_message); - // Add OEmbed and other information to the body - $body = add_page_info_to_body($body, false, true); - $datarray = array(); - $str_tags = ''; - - $tags = get_tags($body); - - if(count($tags)) { - foreach($tags as $tag) { - if(strpos($tag,'#') === 0) { - if(strpos($tag,'[url=')) - continue; - - // don't link tags that are already embedded in links - - if(preg_match('/\[(.*?)' . preg_quote($tag,'/') . '(.*?)\]/',$body)) - continue; - if(preg_match('/\[(.*?)\]\((.*?)' . preg_quote($tag,'/') . '(.*?)\)/',$body)) - continue; + $datarray["object"] = json_encode($xml); - $basetag = str_replace('_',' ',substr($tag,1)); - $body = str_replace($tag,'#[url=' . $a->get_baseurl() . '/search?tag=' . rawurlencode($basetag) . ']' . $basetag . '[/url]',$body); - if(strlen($str_tags)) - $str_tags .= ','; - $str_tags .= '#[url=' . $a->get_baseurl() . '/search?tag=' . rawurlencode($basetag) . ']' . $basetag . '[/url]'; - continue; - } - } + if($xml->photo->remote_photo_path AND $xml->photo->remote_photo_name) + $datarray["object-type"] = ACTIVITY_OBJ_PHOTO; + else { + $datarray['object-type'] = ACTIVITY_OBJ_NOTE; + // Add OEmbed and other information to the body + if (!diaspora_is_redmatrix($contact['url'])) + $body = add_page_info_to_body($body, false, true); } + $str_tags = ''; + $cnt = preg_match_all('/@\[url=(.*?)\[\/url\]/ism',$body,$matches,PREG_SET_ORDER); if($cnt) { foreach($matches as $mtch) { @@ -867,12 +883,13 @@ function diaspora_post($importer,$xml,$msg) { } } - $plink = 'https://'.substr($diaspora_handle,strpos($diaspora_handle,'@')+1).'/posts/'.$guid; + $plink = diaspora_plink($diaspora_handle, $guid); $datarray['uid'] = $importer['uid']; $datarray['contact-id'] = $contact['id']; $datarray['wall'] = 0; - $datarray['network'] = NETWORK_DIASPORA; + $datarray['network'] = NETWORK_DIASPORA; + $datarray['verb'] = ACTIVITY_POST; $datarray['guid'] = $guid; $datarray['uri'] = $datarray['parent-uri'] = $message_id; $datarray['changed'] = $datarray['created'] = $datarray['edited'] = datetime_convert('UTC','UTC',$created); @@ -888,172 +905,321 @@ function diaspora_post($importer,$xml,$msg) { $datarray['author-avatar'] = $contact['thumb']; $datarray['body'] = $body; $datarray['tag'] = $str_tags; - $datarray['app'] = 'Diaspora'; + if ($xml->provider_display_name) + $datarray["app"] = unxmlify($xml->provider_display_name); + else + $datarray['app'] = 'Diaspora'; // if empty content it might be a photo that hasn't arrived yet. If a photo arrives, we'll make it visible. $datarray['visible'] = ((strlen($body)) ? 1 : 0); + DiasporaFetchGuid($datarray); $message_id = item_store($datarray); - //if($message_id) { - // q("update item set plink = '%s' where id = %d", - // dbesc($a->get_baseurl() . '/display/' . $importer['nickname'] . '/' . $message_id), - // intval($message_id) - // ); - //} + logger("Stored item with message id ".$message_id, LOGGER_DEBUG); - return; + return 201; } -function diaspora_reshare($importer,$xml,$msg) { - - logger('diaspora_reshare: init: ' . print_r($xml,true)); +function DiasporaFetchGuid($item) { + preg_replace_callback("&\[url=/posts/([^\[\]]*)\](.*)\[\/url\]&Usi", + function ($match) use ($item){ + return(DiasporaFetchGuidSub($match, $item)); + },$item["body"]); +} +function DiasporaFetchGuidSub($match, $item) { $a = get_app(); - $guid = notags(unxmlify($xml->guid)); - $diaspora_handle = notags(unxmlify($xml->diaspora_handle)); + if (!diaspora_store_by_guid($match[1], $item["author-link"])) + diaspora_store_by_guid($match[1], $item["owner-link"]); +} - if($diaspora_handle != $msg['author']) { - logger('diaspora_post: Potential forgery. Message handle is not the same as envelope sender.'); - return 202; - } +function diaspora_store_by_guid($guid, $server, $uid = 0) { + require_once("include/Contact.php"); - $contact = diaspora_get_contact_by_handle($importer['uid'],$diaspora_handle); - if(! $contact) - return; + $serverparts = parse_url($server); + $server = $serverparts["scheme"]."://".$serverparts["host"]; - if(! diaspora_post_allow($importer,$contact)) { - logger('diaspora_reshare: Ignoring this author: ' . $diaspora_handle . ' ' . print_r($xml,true)); - return 202; - } + logger("Trying to fetch item ".$guid." from ".$server, LOGGER_DEBUG); - $message_id = $diaspora_handle . ':' . $guid; - $r = q("SELECT `id` FROM `item` WHERE `uid` = %d AND `uri` = '%s' AND `guid` = '%s' LIMIT 1", - intval($importer['uid']), - dbesc($message_id), + $item = diaspora_fetch_message($guid, $server); + + if (!$item) + return false; + + logger("Successfully fetched item ".$guid." from ".$server, LOGGER_DEBUG); + + $body = $item["body"]; + $str_tags = $item["tag"]; + $app = $item["app"]; + $created = $item["created"]; + $author = $item["author"]; + $guid = $item["guid"]; + $private = $item["private"]; + $object = $item["object"]; + $objecttype = $item["object-type"]; + + $message_id = $author.':'.$guid; + $r = q("SELECT `id` FROM `item` WHERE `uid` = %d AND `guid` = '%s' LIMIT 1", + intval($uid), dbesc($guid) ); - if(count($r)) { - logger('diaspora_reshare: message exists: ' . $guid); - return; - } + if(count($r)) + return $r[0]["id"]; - $orig_author = notags(unxmlify($xml->root_diaspora_id)); - $orig_guid = notags(unxmlify($xml->root_guid)); + $person = find_diaspora_person_by_handle($author); + + $contact_id = get_contact($person['url'], $uid); + + $contacts = q("SELECT * FROM `contact` WHERE `id` = %d", intval($contact_id)); + $importers = q("SELECT * FROM `user` WHERE `uid` = %d", intval($uid)); + + if ($contacts AND $importers) + if(!diaspora_post_allow($importers[0],$contacts[0], false)) { + logger('Ignoring author '.$person['url'].' for uid '.$uid); + return false; + } else + logger('Author '.$person['url'].' is allowed for uid '.$uid); + + $datarray = array(); + $datarray['uid'] = $uid; + $datarray['contact-id'] = $contact_id; + $datarray['wall'] = 0; + $datarray['network'] = NETWORK_DIASPORA; + $datarray['guid'] = $guid; + $datarray['uri'] = $datarray['parent-uri'] = $message_id; + $datarray['changed'] = $datarray['created'] = $datarray['edited'] = datetime_convert('UTC','UTC',$created); + $datarray['private'] = $private; + $datarray['parent'] = 0; + $datarray['plink'] = diaspora_plink($author, $guid); + $datarray['author-name'] = $person['name']; + $datarray['author-link'] = $person['url']; + $datarray['author-avatar'] = ((x($person,'thumb')) ? $person['thumb'] : $person['photo']); + $datarray['owner-name'] = $datarray['author-name']; + $datarray['owner-link'] = $datarray['author-link']; + $datarray['owner-avatar'] = $datarray['author-avatar']; + $datarray['body'] = $body; + $datarray['tag'] = $str_tags; + $datarray['app'] = $app; + $datarray['visible'] = ((strlen($body)) ? 1 : 0); + $datarray['object'] = $object; + $datarray['object-type'] = $objecttype; - $source_url = 'https://' . substr($orig_author,strpos($orig_author,'@')+1) . '/p/' . $orig_guid . '.xml'; - $orig_url = 'https://'.substr($orig_author,strpos($orig_author,'@')+1).'/posts/'.$orig_guid; + if ($datarray['contact-id'] == 0) + return false; + + DiasporaFetchGuid($datarray); + $message_id = item_store($datarray); + + // To-Do: + // Looking if there is some subscribe mechanism in Diaspora to get all comments for this post + + return $message_id; +} + +function diaspora_fetch_message($guid, $server, $level = 0) { + + if ($level > 5) + return false; + + $a = get_app(); + + // This will not work if the server is not a Diaspora server + $source_url = $server.'/p/'.$guid.'.xml'; $x = fetch_url($source_url); - if(! $x) - $x = fetch_url(str_replace('https://','http://',$source_url)); - if(! $x) { - logger('diaspora_reshare: unable to fetch source url ' . $source_url); - return; - } - logger('diaspora_reshare: source: ' . $x); + if(!$x) + return false; $x = str_replace(array('',''),array('',''),$x); $source_xml = parse_xml_string($x,false); + $item = array(); + $item["app"] = 'Diaspora'; + $item["guid"] = $guid; + $body = ""; + + if ($source_xml->post->status_message->created_at) + $item["created"] = unxmlify($source_xml->post->status_message->created_at); + + if ($source_xml->post->status_message->provider_display_name) + $item["app"] = unxmlify($source_xml->post->status_message->provider_display_name); + + if ($source_xml->post->status_message->diaspora_handle) + $item["author"] = unxmlify($source_xml->post->status_message->diaspora_handle); + + if ($source_xml->post->status_message->guid) + $item["guid"] = unxmlify($source_xml->post->status_message->guid); + + $item["private"] = (unxmlify($source_xml->post->status_message->public) == 'false'); + $item["object"] = json_encode($source_xml->post); + if(strlen($source_xml->post->asphoto->objectId) && ($source_xml->post->asphoto->objectId != 0) && ($source_xml->post->asphoto->image_url)) { + $item["object-type"] = ACTIVITY_OBJ_PHOTO; $body = '[url=' . notags(unxmlify($source_xml->post->asphoto->image_url)) . '][img]' . notags(unxmlify($source_xml->post->asphoto->objectId)) . '[/img][/url]' . "\n"; $body = scale_external_images($body,false); - } - elseif($source_xml->post->asphoto->image_url) { + } elseif($source_xml->post->asphoto->image_url) { + $item["object-type"] = ACTIVITY_OBJ_PHOTO; $body = '[img]' . notags(unxmlify($source_xml->post->asphoto->image_url)) . '[/img]' . "\n"; $body = scale_external_images($body); - } - elseif($source_xml->post->status_message) { + } elseif($source_xml->post->status_message) { $body = diaspora2bb($source_xml->post->status_message->raw_message); // Checking for embedded pictures if($source_xml->post->status_message->photo->remote_photo_path AND $source_xml->post->status_message->photo->remote_photo_name) { + $item["object-type"] = ACTIVITY_OBJ_PHOTO; + $remote_photo_path = notags(unxmlify($source_xml->post->status_message->photo->remote_photo_path)); $remote_photo_name = notags(unxmlify($source_xml->post->status_message->photo->remote_photo_name)); $body = '[img]'.$remote_photo_path.$remote_photo_name.'[/img]'."\n".$body; - logger('diaspora_reshare: embedded picture link found: '.$body, LOGGER_DEBUG); - } + logger('embedded picture link found: '.$body, LOGGER_DEBUG); + } else + $item["object-type"] = ACTIVITY_OBJ_NOTE; $body = scale_external_images($body); // Add OEmbed and other information to the body - $body = add_page_info_to_body($body, false, true); - } - else { + // To-Do: It could be a repeated redmatrix item + // Then we shouldn't add further data to it + if ($item["object-type"] == ACTIVITY_OBJ_NOTE) + $body = add_page_info_to_body($body, false, true); + + } elseif($source_xml->post->reshare) { + // Reshare of a reshare + return diaspora_fetch_message($source_xml->post->reshare->root_guid, $server, ++$level); + } else { // Maybe it is a reshare of a photo that will be delivered at a later time (testing) - logger('diaspora_reshare: no reshare content found: ' . print_r($source_xml,true)); - $body = ""; - //return; + logger('no content found: '.print_r($source_xml,true)); + return false; } - //if(! $body) { - // logger('diaspora_reshare: empty body: source= ' . $x); - // return; - //} + if (trim($body) == "") + return false; - $person = find_diaspora_person_by_handle($orig_author); + $item["tag"] = ''; + $item["body"] = $body; - /*if(is_array($person) && x($person,'name') && x($person,'url')) - $details = '[url=' . $person['url'] . ']' . $person['name'] . '[/url]'; - else - $details = $orig_author; + return $item; +} + +function diaspora_reshare($importer,$xml,$msg) { - $prefix = html_entity_decode("♲ ", ENT_QUOTES, 'UTF-8') . $details . "\n";*/ + logger('diaspora_reshare: init: ' . print_r($xml,true)); + $a = get_app(); + $guid = notags(unxmlify($xml->guid)); + $diaspora_handle = notags(unxmlify($xml->diaspora_handle)); - // allocate a guid on our system - we aren't fixing any collisions. - // we're ignoring them - $g = q("select * from guid where guid = '%s' limit 1", + if($diaspora_handle != $msg['author']) { + logger('diaspora_post: Potential forgery. Message handle is not the same as envelope sender.'); + return 202; + } + + $contact = diaspora_get_contact_by_handle($importer['uid'],$diaspora_handle); + if(! $contact) + return; + + if(! diaspora_post_allow($importer,$contact, false)) { + logger('diaspora_reshare: Ignoring this author: ' . $diaspora_handle . ' ' . print_r($xml,true)); + return 202; + } + + $message_id = $diaspora_handle . ':' . $guid; + $r = q("SELECT `id` FROM `item` WHERE `uid` = %d AND `guid` = '%s' LIMIT 1", + intval($importer['uid']), dbesc($guid) ); - if(! count($g)) { - q("insert into guid ( guid ) values ( '%s' )", - dbesc($guid) - ); + if(count($r)) { + logger('diaspora_reshare: message exists: ' . $guid); + return; } - $created = unxmlify($xml->created_at); - $private = ((unxmlify($xml->public) == 'false') ? 1 : 0); - - $datarray = array(); + $orig_author = notags(unxmlify($xml->root_diaspora_id)); + $orig_guid = notags(unxmlify($xml->root_guid)); + $orig_url = $a->get_baseurl()."/display/".$orig_guid; - $str_tags = ''; + $create_original_post = false; - $tags = get_tags($body); + // Do we already have this item? + $r = q("SELECT `body`, `tag`, `app`, `created`, `plink`, `object`, `object-type`, `uri` FROM `item` WHERE `guid` = '%s' AND `visible` AND NOT `deleted` AND `body` != '' LIMIT 1", + dbesc($orig_guid), + dbesc(NETWORK_DIASPORA) + ); + if(count($r)) { + logger('reshared message '.$orig_guid." reshared by ".$guid.' already exists on system.'); - if(count($tags)) { - foreach($tags as $tag) { - if(strpos($tag,'#') === 0) { - if(strpos($tag,'[url=')) - continue; + // Maybe it is already a reshared item? + // Then refetch the content, since there can be many side effects with reshared posts from other networks or reshares from reshares + require_once('include/api.php'); + if (api_share_as_retweet($r[0])) + $r = array(); + else { + $body = $r[0]["body"]; + $str_tags = $r[0]["tag"]; + $app = $r[0]["app"]; + $orig_created = $r[0]["created"]; + $orig_plink = $r[0]["plink"]; + $orig_uri = $r[0]["uri"]; + $object = $r[0]["object"]; + $objecttype = $r[0]["object-type"]; + } + } - // don't link tags that are already embedded in links + if (!count($r)) { + $body = ""; + $str_tags = ""; + $app = ""; - if(preg_match('/\[(.*?)' . preg_quote($tag,'/') . '(.*?)\]/',$body)) - continue; - if(preg_match('/\[(.*?)\]\((.*?)' . preg_quote($tag,'/') . '(.*?)\)/',$body)) - continue; + $server = 'https://'.substr($orig_author,strpos($orig_author,'@')+1); + logger('1st try: reshared message '.$orig_guid." reshared by ".$guid.' will be fetched from original server: '.$server); + $item = diaspora_fetch_message($orig_guid, $server); + if (!$item) { + $server = 'https://'.substr($diaspora_handle,strpos($diaspora_handle,'@')+1); + logger('2nd try: reshared message '.$orig_guid." reshared by ".$guid." will be fetched from sharer's server: ".$server); + $item = diaspora_fetch_message($orig_guid, $server); + } + if (!$item) { + $server = 'http://'.substr($orig_author,strpos($orig_author,'@')+1); + logger('3rd try: reshared message '.$orig_guid." reshared by ".$guid.' will be fetched from original server: '.$server); + $item = diaspora_fetch_message($orig_guid, $server); + } + if (!$item) { + $server = 'http://'.substr($diaspora_handle,strpos($diaspora_handle,'@')+1); + logger('4th try: reshared message '.$orig_guid." reshared by ".$guid." will be fetched from sharer's server: ".$server); + $item = diaspora_fetch_message($orig_guid, $server); + } - $basetag = str_replace('_',' ',substr($tag,1)); - $body = str_replace($tag,'#[url=' . $a->get_baseurl() . '/search?tag=' . rawurlencode($basetag) . ']' . $basetag . '[/url]',$body); - if(strlen($str_tags)) - $str_tags .= ','; - $str_tags .= '#[url=' . $a->get_baseurl() . '/search?tag=' . rawurlencode($basetag) . ']' . $basetag . '[/url]'; - continue; - } + if ($item) { + $body = $item["body"]; + $str_tags = $item["tag"]; + $app = $item["app"]; + $orig_created = $item["created"]; + $orig_author = $item["author"]; + $orig_guid = $item["guid"]; + $orig_plink = diaspora_plink($orig_author, $orig_guid); + $orig_uri = $orig_author.':'.$orig_guid; + $create_original_post = ($body != ""); + $object = $item["object"]; + $objecttype = $item["object-type"]; } } - $plink = 'https://'.substr($diaspora_handle,strpos($diaspora_handle,'@')+1).'/posts/'.$guid; + $plink = diaspora_plink($diaspora_handle, $guid); + + $person = find_diaspora_person_by_handle($orig_author); + + $created = unxmlify($xml->created_at); + $private = ((unxmlify($xml->public) == 'false') ? 1 : 0); + + $datarray = array(); $datarray['uid'] = $importer['uid']; $datarray['contact-id'] = $contact['id']; @@ -1069,10 +1235,8 @@ function diaspora_reshare($importer,$xml,$msg) { $datarray['owner-link'] = $contact['url']; $datarray['owner-avatar'] = ((x($contact,'thumb')) ? $contact['thumb'] : $contact['photo']); if (!intval(get_config('system','wall-to-wall_share'))) { - $prefix = "[share author='".str_replace(array("'", "[", "]"), array("'", "[", "]"),$person['name']). - "' profile='".$person['url']. - "' avatar='".((x($person,'thumb')) ? $person['thumb'] : $person['photo']). - "' link='".str_replace(array("'", "[", "]"), array("'", "[", "]"),$orig_url)."']"; + $prefix = share_header($person['name'], $person['url'], ((x($person,'thumb')) ? $person['thumb'] : $person['photo']), $orig_guid, $orig_created, $orig_url); + $datarray['author-name'] = $contact['name']; $datarray['author-link'] = $contact['url']; $datarray['author-avatar'] = $contact['thumb']; @@ -1085,20 +1249,46 @@ function diaspora_reshare($importer,$xml,$msg) { $datarray['body'] = $body; } + $datarray["object"] = json_encode($xml); + $datarray['object-type'] = $objecttype; + $datarray['tag'] = $str_tags; - $datarray['app'] = 'Diaspora'; + $datarray['app'] = $app; // if empty content it might be a photo that hasn't arrived yet. If a photo arrives, we'll make it visible. (testing) $datarray['visible'] = ((strlen($body)) ? 1 : 0); - $message_id = item_store($datarray); + // Store the original item of a reshare + if ($create_original_post) { + require_once("include/Contact.php"); - //if($message_id) { - // q("update item set plink = '%s' where id = %d", - // dbesc($a->get_baseurl() . '/display/' . $importer['nickname'] . '/' . $message_id), - // intval($message_id) - // ); - //} + $datarray2 = $datarray; + + $datarray2['uid'] = 0; + $datarray2['contact-id'] = get_contact($person['url'], 0); + $datarray2['guid'] = $orig_guid; + $datarray2['uri'] = $datarray2['parent-uri'] = $orig_uri; + $datarray2['changed'] = $datarray2['created'] = $datarray2['edited'] = $datarray2['commented'] = $datarray2['received'] = datetime_convert('UTC','UTC',$orig_created); + $datarray2['parent'] = 0; + $datarray2['plink'] = $orig_plink; + + $datarray2['author-name'] = $person['name']; + $datarray2['author-link'] = $person['url']; + $datarray2['author-avatar'] = ((x($person,'thumb')) ? $person['thumb'] : $person['photo']); + $datarray2['owner-name'] = $datarray2['author-name']; + $datarray2['owner-link'] = $datarray2['author-link']; + $datarray2['owner-avatar'] = $datarray2['author-avatar']; + $datarray2['body'] = $body; + $datarray2["object"] = $object; + + DiasporaFetchGuid($datarray2); + $message_id = item_store($datarray2); + + logger("Store original item ".$orig_guid." under message id ".$message_id); + } + + DiasporaFetchGuid($datarray); + $message_id = item_store($datarray); return; @@ -1121,15 +1311,14 @@ function diaspora_asphoto($importer,$xml,$msg) { if(! $contact) return; - if(! diaspora_post_allow($importer,$contact)) { + if(! diaspora_post_allow($importer,$contact, false)) { logger('diaspora_asphoto: Ignoring this author.'); return 202; } $message_id = $diaspora_handle . ':' . $guid; - $r = q("SELECT `id` FROM `item` WHERE `uid` = %d AND `uri` = '%s' AND `guid` = '%s' LIMIT 1", + $r = q("SELECT `id` FROM `item` WHERE `uid` = %d AND `guid` = '%s' LIMIT 1", intval($importer['uid']), - dbesc($message_id), dbesc($guid) ); if(count($r)) { @@ -1137,18 +1326,6 @@ function diaspora_asphoto($importer,$xml,$msg) { return; } - // allocate a guid on our system - we aren't fixing any collisions. - // we're ignoring them - - $g = q("select * from guid where guid = '%s' limit 1", - dbesc($guid) - ); - if(! count($g)) { - q("insert into guid ( guid ) values ( '%s' )", - dbesc($guid) - ); - } - $created = unxmlify($xml->created_at); $private = ((unxmlify($xml->public) == 'false') ? 1 : 0); @@ -1165,7 +1342,7 @@ function diaspora_asphoto($importer,$xml,$msg) { return; } - $plink = 'https://'.substr($diaspora_handle,strpos($diaspora_handle,'@')+1).'/posts/'.$guid; + $plink = diaspora_plink($diaspora_handle, $guid); $datarray = array(); @@ -1187,9 +1364,12 @@ function diaspora_asphoto($importer,$xml,$msg) { $datarray['author-link'] = $contact['url']; $datarray['author-avatar'] = $contact['thumb']; $datarray['body'] = $body; + $datarray["object"] = json_encode($xml); + $datarray['object-type'] = ACTIVITY_OBJ_PHOTO; $datarray['app'] = 'Diaspora/Cubbi.es'; + DiasporaFetchGuid($datarray); $message_id = item_store($datarray); //if($message_id) { @@ -1226,7 +1406,7 @@ function diaspora_comment($importer,$xml,$msg) { return; } - if(! diaspora_post_allow($importer,$contact)) { + if(! diaspora_post_allow($importer,$contact, true)) { logger('diaspora_comment: Ignoring this author.'); return 202; } @@ -1244,6 +1424,25 @@ function diaspora_comment($importer,$xml,$msg) { intval($importer['uid']), dbesc($parent_guid) ); + + if(!count($r)) { + $result = diaspora_store_by_guid($parent_guid, $contact['url'], $importer['uid']); + + if (!$result) { + $person = find_diaspora_person_by_handle($diaspora_handle); + $result = diaspora_store_by_guid($parent_guid, $person['url'], $importer['uid']); + } + + if ($result) { + logger("Fetched missing item ".$parent_guid." - result: ".$result, LOGGER_DEBUG); + + $r = q("SELECT * FROM `item` WHERE `uid` = %d AND `guid` = '%s' LIMIT 1", + intval($importer['uid']), + dbesc($parent_guid) + ); + } + } + if(! count($r)) { logger('diaspora_comment: parent item not found: parent: ' . $parent_guid . ' item: ' . $guid); return; @@ -1313,39 +1512,12 @@ function diaspora_comment($importer,$xml,$msg) { $datarray = array(); - $str_tags = ''; - - $tags = get_tags($body); - - if(count($tags)) { - foreach($tags as $tag) { - if(strpos($tag,'#') === 0) { - if(strpos($tag,'[url=')) - continue; - - // don't link tags that are already embedded in links - - if(preg_match('/\[(.*?)' . preg_quote($tag,'/') . '(.*?)\]/',$body)) - continue; - if(preg_match('/\[(.*?)\]\((.*?)' . preg_quote($tag,'/') . '(.*?)\)/',$body)) - continue; - - - $basetag = str_replace('_',' ',substr($tag,1)); - $body = str_replace($tag,'#[url=' . $a->get_baseurl() . '/search?tag=' . rawurlencode($basetag) . ']' . $basetag . '[/url]',$body); - if(strlen($str_tags)) - $str_tags .= ','; - $str_tags .= '#[url=' . $a->get_baseurl() . '/search?tag=' . rawurlencode($basetag) . ']' . $basetag . '[/url]'; - continue; - } - } - } - $datarray['uid'] = $importer['uid']; $datarray['contact-id'] = $contact['id']; $datarray['type'] = 'remote-comment'; $datarray['wall'] = $parent_item['wall']; $datarray['network'] = NETWORK_DIASPORA; + $datarray['verb'] = ACTIVITY_POST; $datarray['gravity'] = GRAVITY_COMMENT; $datarray['guid'] = $guid; $datarray['uri'] = $message_id; @@ -1363,20 +1535,25 @@ function diaspora_comment($importer,$xml,$msg) { $datarray['author-link'] = $person['url']; $datarray['author-avatar'] = ((x($person,'thumb')) ? $person['thumb'] : $person['photo']); $datarray['body'] = $body; - $datarray['tag'] = $str_tags; + $datarray["object"] = json_encode($xml); + $datarray["object-type"] = ACTIVITY_OBJ_COMMENT; // We can't be certain what the original app is if the message is relayed. if(($parent_item['origin']) && (! $parent_author_signature)) $datarray['app'] = 'Diaspora'; + DiasporaFetchGuid($datarray); $message_id = item_store($datarray); - if($message_id) { - q("update item set plink = '%s' where id = %d", - dbesc($a->get_baseurl() . '/display/' . $importer['nickname'] . '/' . $message_id), - intval($message_id) - ); - } + $datarray['id'] = $message_id; + + //if($message_id) { + //q("update item set plink = '%s' where id = %d", + // //dbesc($a->get_baseurl() . '/display/' . $importer['nickname'] . '/' . $message_id), + // dbesc($a->get_baseurl().'/display/'.$datarray['guid']), + // intval($message_id) + //); + //} if(($parent_item['origin']) && (! $parent_author_signature)) { q("insert into sign (`iid`,`signed_text`,`signature`,`signer`) values (%d,'%s','%s','%s') ", @@ -1420,7 +1597,7 @@ function diaspora_comment($importer,$xml,$msg) { 'to_email' => $importer['email'], 'uid' => $importer['uid'], 'item' => $datarray, - 'link' => $a->get_baseurl() . '/display/' . $importer['nickname'] . '/' . $message_id, + 'link' => $a->get_baseurl().'/display/'.urlencode($datarray['guid']), 'source_name' => $datarray['author-name'], 'source_link' => $datarray['author-link'], 'source_photo' => $datarray['author-avatar'], @@ -1451,7 +1628,7 @@ function diaspora_conversation($importer,$xml,$msg) { $created_at = datetime_convert('UTC','UTC',notags(unxmlify($xml->created_at))); $parent_uri = $diaspora_handle . ':' . $guid; - + $messages = $xml->message; if(! count($messages)) { @@ -1465,7 +1642,7 @@ function diaspora_conversation($importer,$xml,$msg) { return; } - if(($contact['rel'] == CONTACT_IS_FOLLOWER) || ($contact['blocked']) || ($contact['readonly'])) { + if(($contact['rel'] == CONTACT_IS_FOLLOWER) || ($contact['blocked']) || ($contact['readonly'])) { logger('diaspora_conversation: Ignoring this author.'); return 202; } @@ -1490,11 +1667,11 @@ function diaspora_conversation($importer,$xml,$msg) { ); if($r) $c = q("select * from conv where uid = %d and guid = '%s' limit 1", - intval($importer['uid']), - dbesc($guid) - ); + intval($importer['uid']), + dbesc($guid) + ); if(count($c)) - $conversation = $c[0]; + $conversation = $c[0]; } if(! $conversation) { logger('diaspora_conversation: unable to create conversation.'); @@ -1573,7 +1750,7 @@ function diaspora_conversation($importer,$xml,$msg) { dbesc($person['name']), dbesc($person['photo']), dbesc($person['url']), - intval($contact['id']), + intval($contact['id']), dbesc($subject), dbesc($body), 0, @@ -1595,7 +1772,7 @@ function diaspora_conversation($importer,$xml,$msg) { 'language' => $importer['language'], 'to_name' => $importer['username'], 'to_email' => $importer['email'], - 'uid' =>$importer['importer_uid'], + 'uid' =>$importer['uid'], 'item' => array('subject' => $subject, 'body' => $body), 'source_name' => $person['name'], 'source_link' => $person['url'], @@ -1603,7 +1780,7 @@ function diaspora_conversation($importer,$xml,$msg) { 'verb' => ACTIVITY_POST, 'otype' => 'mail' )); - } + } return; } @@ -1621,15 +1798,15 @@ function diaspora_message($importer,$xml,$msg) { $msg_diaspora_handle = notags(unxmlify($xml->diaspora_handle)); $msg_conversation_guid = notags(unxmlify($xml->conversation_guid)); - $parent_uri = $diaspora_handle . ':' . $msg_parent_guid; - + $parent_uri = $msg_diaspora_handle . ':' . $msg_parent_guid; + $contact = diaspora_get_contact_by_handle($importer['uid'],$msg_diaspora_handle); if(! $contact) { logger('diaspora_message: cannot find contact: ' . $msg_diaspora_handle); return; } - if(($contact['rel'] == CONTACT_IS_FOLLOWER) || ($contact['blocked']) || ($contact['readonly'])) { + if(($contact['rel'] == CONTACT_IS_FOLLOWER) || ($contact['blocked']) || ($contact['readonly'])) { logger('diaspora_message: Ignoring this author.'); return 202; } @@ -1686,7 +1863,7 @@ function diaspora_message($importer,$xml,$msg) { dbesc($person['name']), dbesc($person['photo']), dbesc($person['url']), - intval($contact['id']), + intval($contact['id']), dbesc($conversation['subject']), dbesc($body), 0, @@ -1733,7 +1910,7 @@ function diaspora_photo($importer,$xml,$msg,$attempt=1) { return; } - if(! diaspora_post_allow($importer,$contact)) { + if(! diaspora_post_allow($importer,$contact, false)) { logger('diaspora_photo: Ignoring this author.'); return 202; } @@ -1742,7 +1919,27 @@ function diaspora_photo($importer,$xml,$msg,$attempt=1) { intval($importer['uid']), dbesc($status_message_guid) ); - if(! count($r)) { + +/* deactivated by now since it can lead to multiplicated pictures in posts. + if(!count($r)) { + $result = diaspora_store_by_guid($status_message_guid, $contact['url'], $importer['uid']); + + if (!$result) { + $person = find_diaspora_person_by_handle($diaspora_handle); + $result = diaspora_store_by_guid($status_message_guid, $person['url'], $importer['uid']); + } + + if ($result) { + logger("Fetched missing item ".$status_message_guid." - result: ".$result, LOGGER_DEBUG); + + $r = q("SELECT * FROM `item` WHERE `uid` = %d AND `guid` = '%s' LIMIT 1", + intval($importer['uid']), + dbesc($status_message_guid) + ); + } + } +*/ + if(!count($r)) { if($attempt <= 3) { q("INSERT INTO dsprphotoq (uid, msg, attempt) VALUES (%d, '%s', %d)", intval($importer['uid']), @@ -1750,6 +1947,7 @@ function diaspora_photo($importer,$xml,$msg,$attempt=1) { intval($attempt + 1) ); } + logger('diaspora_photo: attempt = ' . $attempt . '; status message not found: ' . $status_message_guid . ' for photo: ' . $guid); return; } @@ -1759,14 +1957,15 @@ function diaspora_photo($importer,$xml,$msg,$attempt=1) { $link_text = '[img]' . $remote_photo_path . $remote_photo_name . '[/img]' . "\n"; $link_text = scale_external_images($link_text, true, - array($remote_photo_name, 'scaled_full_' . $remote_photo_name)); + array($remote_photo_name, 'scaled_full_' . $remote_photo_name)); if(strpos($parent_item['body'],$link_text) === false) { - $r = q("update item set `body` = '%s', `visible` = 1 where `id` = %d and `uid` = %d", + $r = q("UPDATE `item` SET `body` = '%s', `visible` = 1 WHERE `id` = %d AND `uid` = %d", dbesc($link_text . $parent_item['body']), intval($parent_item['id']), intval($parent_item['uid']) ); + update_thread($parent_item['id']); } return; @@ -1798,7 +1997,7 @@ function diaspora_like($importer,$xml,$msg) { return; } - if(! diaspora_post_allow($importer,$contact)) { + if(! diaspora_post_allow($importer,$contact, false)) { logger('diaspora_like: Ignoring this author.'); return 202; } @@ -1807,6 +2006,25 @@ function diaspora_like($importer,$xml,$msg) { intval($importer['uid']), dbesc($parent_guid) ); + + if(!count($r)) { + $result = diaspora_store_by_guid($parent_guid, $contact['url'], $importer['uid']); + + if (!$result) { + $person = find_diaspora_person_by_handle($diaspora_handle); + $result = diaspora_store_by_guid($parent_guid, $person['url'], $importer['uid']); + } + + if ($result) { + logger("Fetched missing item ".$parent_guid." - result: ".$result, LOGGER_DEBUG); + + $r = q("SELECT * FROM `item` WHERE `uid` = %d AND `guid` = '%s' LIMIT 1", + intval($importer['uid']), + dbesc($parent_guid) + ); + } + } + if(! count($r)) { logger('diaspora_like: parent item not found: ' . $guid); return; @@ -1841,7 +2059,7 @@ function diaspora_like($importer,$xml,$msg) { if($positive === 'false') { logger('diaspora_like: received a like with positive set to "false"'); logger('diaspora_like: unlike received with no corresponding like...ignoring'); - return; + return; } @@ -1857,22 +2075,28 @@ function diaspora_like($importer,$xml,$msg) { who sent the salmon */ - $signed_data = $guid . ';' . $target_type . ';' . $parent_guid . ';' . $positive . ';' . $diaspora_handle; + // Diaspora has changed the way they are signing the likes. + // Just to make sure that we don't miss any likes we will check the old and the current way. + $old_signed_data = $guid . ';' . $target_type . ';' . $parent_guid . ';' . $positive . ';' . $diaspora_handle; + + $signed_data = $positive . ';' . $guid . ';' . $target_type . ';' . $parent_guid . ';' . $diaspora_handle; + $key = $msg['key']; - if($parent_author_signature) { + if ($parent_author_signature) { // If a parent_author_signature exists, then we've received the like // relayed from the top-level post owner. There's no need to check the // author_signature if the parent_author_signature is valid $parent_author_signature = base64_decode($parent_author_signature); - if(! rsa_verify($signed_data,$parent_author_signature,$key,'sha256')) { + if (!rsa_verify($signed_data,$parent_author_signature,$key,'sha256') AND + !rsa_verify($old_signed_data,$parent_author_signature,$key,'sha256')) { + logger('diaspora_like: top-level owner verification failed.'); return; } - } - else { + } else { // If there's no parent_author_signature, then we've received the like // from the like creator. In that case, the person is "like"ing // our post, so he/she must be a contact of ours and his/her public key @@ -1880,7 +2104,9 @@ function diaspora_like($importer,$xml,$msg) { $author_signature = base64_decode($author_signature); - if(! rsa_verify($signed_data,$author_signature,$key,'sha256')) { + if (!rsa_verify($signed_data,$author_signature,$key,'sha256') AND + !rsa_verify($old_signed_data,$author_signature,$key,'sha256')) { + logger('diaspora_like: like creator verification failed.'); return; } @@ -1906,7 +2132,7 @@ function diaspora_like($importer,$xml,$msg) { $activity = ACTIVITY_LIKE; $post_type = (($parent_item['resource-id']) ? t('photo') : t('status')); - $objtype = (($parent_item['resource-id']) ? ACTIVITY_OBJ_PHOTO : ACTIVITY_OBJ_NOTE ); + $objtype = (($parent_item['resource-id']) ? ACTIVITY_OBJ_PHOTO : ACTIVITY_OBJ_NOTE ); $link = xmlify('' . "\n") ; $body = $parent_item['body']; @@ -1947,7 +2173,8 @@ EOT; $ulink = '[url=' . $contact['url'] . ']' . $contact['name'] . '[/url]'; $alink = '[url=' . $parent_item['author-link'] . ']' . $parent_item['author-name'] . '[/url]'; - $plink = '[url=' . $a->get_baseurl() . '/display/' . $importer['nickname'] . '/' . $parent_item['id'] . ']' . $post_type . '[/url]'; + //$plink = '[url=' . $a->get_baseurl() . '/display/' . $importer['nickname'] . '/' . $parent_item['id'] . ']' . $post_type . '[/url]'; + $plink = '[url='.$a->get_baseurl().'/display/'.urlencode($guid).']'.$post_type.'[/url]'; $arr['body'] = sprintf( $bodyverb, $ulink, $alink, $plink ); $arr['app'] = 'Diaspora'; @@ -1963,12 +2190,13 @@ EOT; $message_id = item_store($arr); - if($message_id) { - q("update item set plink = '%s' where id = %d", - dbesc($a->get_baseurl() . '/display/' . $importer['nickname'] . '/' . $message_id), - intval($message_id) - ); - } + //if($message_id) { + // q("update item set plink = '%s' where id = %d", + // //dbesc($a->get_baseurl() . '/display/' . $importer['nickname'] . '/' . $message_id), + // dbesc($a->get_baseurl().'/display/'.$guid), + // intval($message_id) + // ); + //} if(! $parent_author_signature) { q("insert into sign (`iid`,`signed_text`,`signature`,`signer`) values (%d,'%s','%s','%s') ", @@ -2015,6 +2243,7 @@ function diaspora_retraction($importer,$xml) { dbesc(datetime_convert()), intval($r[0]['id']) ); + delete_thread($r[0]['id'], $r[0]['parent-uri']); } } } @@ -2087,6 +2316,7 @@ function diaspora_signed_retraction($importer,$xml,$msg) { dbesc(datetime_convert()), intval($r[0]['id']) ); + delete_thread($r[0]['id'], $r[0]['parent-uri']); // Now check if the retraction needs to be relayed by us // @@ -2146,14 +2376,27 @@ function diaspora_profile($importer,$xml,$msg) { $name = unxmlify($xml->first_name) . ((strlen($xml->last_name)) ? ' ' . unxmlify($xml->last_name) : ''); $image_url = unxmlify($xml->image_url); $birthday = unxmlify($xml->birthday); + $location = diaspora2bb(unxmlify($xml->location)); + $about = diaspora2bb(unxmlify($xml->bio)); + $gender = unxmlify($xml->gender); + $tags = unxmlify($xml->tag_string); + + $tags = explode("#", $tags); + $keywords = array(); + foreach ($tags as $tag) { + $tag = trim(strtolower($tag)); + if ($tag != "") + $keywords[] = $tag; + } + + $keywords = implode(", ", $keywords); $handle_parts = explode("@", $diaspora_handle); if($name === '') { $name = $handle_parts[0]; } - - + if( preg_match("|^https?://|", $image_url) === 0) { $image_url = "http://" . $handle_parts[1] . $image_url; } @@ -2167,8 +2410,8 @@ function diaspora_profile($importer,$xml,$msg) { require_once('include/Photo.php'); $images = import_profile_photo($image_url,$importer['uid'],$contact['id']); - - // Generic birthday. We don't know the timezone. The year is irrelevant. + + // Generic birthday. We don't know the timezone. The year is irrelevant. $birthday = str_replace('1000','1901',$birthday); @@ -2181,9 +2424,9 @@ function diaspora_profile($importer,$xml,$msg) { $birthday = $contact['bd']; // TODO: update name on item['author-name'] if the name changed. See consume_feed() - // Not doing this currently because D* protocol is scheduled for revision soon. + // Not doing this currently because D* protocol is scheduled for revision soon. - $r = q("UPDATE `contact` SET `name` = '%s', `name-date` = '%s', `photo` = '%s', `thumb` = '%s', `micro` = '%s', `avatar-date` = '%s' , `bd` = '%s' WHERE `id` = %d AND `uid` = %d", + $r = q("UPDATE `contact` SET `name` = '%s', `name-date` = '%s', `photo` = '%s', `thumb` = '%s', `micro` = '%s', `avatar-date` = '%s' , `bd` = '%s', `location` = '%s', `about` = '%s', `keywords` = '%s', `gender` = '%s' WHERE `id` = %d AND `uid` = %d", dbesc($name), dbesc(datetime_convert()), dbesc($images[0]), @@ -2191,9 +2434,34 @@ function diaspora_profile($importer,$xml,$msg) { dbesc($images[2]), dbesc(datetime_convert()), dbesc($birthday), + dbesc($location), + dbesc($about), + dbesc($keywords), + dbesc($gender), intval($contact['id']), intval($importer['uid']) - ); + ); + + 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(), 2, $contact['id'], $importer['uid']); + } + + $profileurl = ""; + $author = q("SELECT * FROM `unique_contacts` WHERE `url`='%s' LIMIT 1", + dbesc(normalise_link($contact['url']))); + + if (count($author) == 0) { + q("INSERT INTO `unique_contacts` (`url`, `name`, `avatar`, `location`, `about`) VALUES ('%s', '%s', '%s', '%s', '%s')", + dbesc(normalise_link($contact['url'])), dbesc($name), dbesc($location), dbesc($about), dbesc($images[0])); + + $author = q("SELECT id FROM unique_contacts WHERE url='%s' LIMIT 1", + dbesc(normalise_link($contact['url']))); + } else if (normalise_link($contact['url']).$name.$location.$about != normalise_link($author[0]["url"]).$author[0]["name"].$author[0]["location"].$author[0]["about"]) { + q("UPDATE unique_contacts SET name = '%s', avatar = '%s', `location` = '%s', `about` = '%s' WHERE url = '%s'", + dbesc($name), dbesc($images[0]), dbesc($location), dbesc($about), dbesc(normalise_link($contact['url']))); + } /* if($r) { if($oldphotos) { @@ -2301,7 +2569,7 @@ function diaspora_send_status($item,$owner,$contact,$public_batch = false) { $body .= '[' . $mtch[3] . '](' . $mtch[1] . ')' . "\n"; } } - } + } $public = (($item['private']) ? 'false' : 'true'); @@ -2309,22 +2577,40 @@ function diaspora_send_status($item,$owner,$contact,$public_batch = false) { require_once('include/datetime.php'); $created = datetime_convert('UTC','UTC',$item['created'],'Y-m-d H:i:s \U\T\C'); - $tpl = get_markup_template('diaspora_post.tpl'); - $msg = replace_macros($tpl, array( - '$body' => $body, - '$guid' => $item['guid'], - '$handle' => xmlify($myaddr), - '$public' => $public, - '$created' => $created - )); + // Detect a share element and do a reshare + // see: https://github.com/Raven24/diaspora-federation/blob/master/lib/diaspora-federation/entities/reshare.rb + if (!$item['private'] AND ($ret = diaspora_is_reshare($item["body"]))) { + $tpl = get_markup_template('diaspora_reshare.tpl'); + $msg = replace_macros($tpl, array( + '$root_handle' => xmlify($ret['root_handle']), + '$root_guid' => $ret['root_guid'], + '$guid' => $item['guid'], + '$handle' => xmlify($myaddr), + '$public' => $public, + '$created' => $created, + '$provider' => $item["app"] + )); + } else { + $tpl = get_markup_template('diaspora_post.tpl'); + $msg = replace_macros($tpl, array( + '$body' => $body, + '$guid' => $item['guid'], + '$handle' => xmlify($myaddr), + '$public' => $public, + '$created' => $created, + '$provider' => $item["app"] + )); + } - logger('diaspora_send_status: ' . $owner['username'] . ' -> ' . $contact['name'] . ' base message: ' . $msg, LOGGER_DATA); + logger('diaspora_send_status: '.$owner['username'].' -> '.$contact['name'].' base message: '.$msg, LOGGER_DATA); $slap = 'xml=' . urlencode(urlencode(diaspora_msg_build($msg,$owner,$contact,$owner['uprvkey'],$contact['pubkey'],$public_batch))); //$slap = 'xml=' . urlencode(diaspora_msg_build($msg,$owner,$contact,$owner['uprvkey'],$contact['pubkey'],$public_batch)); $return_code = diaspora_transmit($owner,$contact,$slap,$public_batch); + logger('diaspora_send_status: guid: '.$item['guid'].' result '.$return_code, LOGGER_DEBUG); + if(count($images)) { diaspora_send_images($item,$owner,$contact,$images,$public_batch); } @@ -2332,6 +2618,73 @@ function diaspora_send_status($item,$owner,$contact,$public_batch = false) { return $return_code; } +function diaspora_is_reshare($body) { + $body = trim($body); + + // Skip if it isn't a pure repeated messages + // Does it start with a share? + if (strpos($body, "[share") > 0) + return(false); + + // Does it end with a share? + if (strlen($body) > (strrpos($body, "[/share]") + 8)) + return(false); + + $attributes = preg_replace("/\[share(.*?)\]\s?(.*?)\s?\[\/share\]\s?/ism","$1",$body); + // Skip if there is no shared message in there + if ($body == $attributes) + return(false); + + $guid = ""; + preg_match("/guid='(.*?)'/ism", $attributes, $matches); + if ($matches[1] != "") + $guid = $matches[1]; + + preg_match('/guid="(.*?)"/ism', $attributes, $matches); + if ($matches[1] != "") + $guid = $matches[1]; + + if ($guid != "") { + $r = q("SELECT `contact-id` FROM `item` WHERE `guid` = '%s' AND `network` IN ('%s', '%s') LIMIT 1", + dbesc($guid), NETWORK_DFRN, NETWORK_DIASPORA); + if ($r) { + $ret= array(); + $ret["root_handle"] = diaspora_handle_from_contact($r[0]["contact-id"]); + $ret["root_guid"] = $guid; + return($ret); + } + } + + $profile = ""; + preg_match("/profile='(.*?)'/ism", $attributes, $matches); + if ($matches[1] != "") + $profile = $matches[1]; + + preg_match('/profile="(.*?)"/ism', $attributes, $matches); + if ($matches[1] != "") + $profile = $matches[1]; + + $ret= array(); + + $ret["root_handle"] = preg_replace("=https?://(.*)/u/(.*)=ism", "$2@$1", $profile); + if (($ret["root_handle"] == $profile) OR ($ret["root_handle"] == "")) + return(false); + + $link = ""; + preg_match("/link='(.*?)'/ism", $attributes, $matches); + if ($matches[1] != "") + $link = $matches[1]; + + preg_match('/link="(.*?)"/ism', $attributes, $matches); + if ($matches[1] != "") + $link = $matches[1]; + + $ret["root_guid"] = preg_replace("=https?://(.*)/posts/(.*)=ism", "$2", $link); + if (($ret["root_guid"] == $link) OR ($ret["root_guid"] == "")) + return(false); + + return($ret); +} function diaspora_send_images($item,$owner,$contact,$images,$public_batch = false) { $a = get_app(); @@ -2384,7 +2737,7 @@ function diaspora_send_followup($item,$owner,$contact,$public_batch = false) { // likes on comments if($item['verb'] === ACTIVITY_LIKE && $item['thr-parent']) { $p = q("select guid, type, uri, `parent-uri` from item where uri = '%s' limit 1", - dbesc($item['thr-parent']) + dbesc($item['thr-parent']) ); } else { @@ -2462,7 +2815,7 @@ function diaspora_send_relay($item,$owner,$contact,$public_batch = false) { // likes on comments if($item['verb'] === ACTIVITY_LIKE && $item['thr-parent']) { $p = q("select guid, type, uri, `parent-uri` from item where uri = '%s' limit 1", - dbesc($item['thr-parent']) + dbesc($item['thr-parent']) ); } else { @@ -2598,7 +2951,7 @@ function diaspora_send_retraction($item,$owner,$contact,$public_batch = false) { $target_type = (($item['verb'] === ACTIVITY_LIKE) ? 'Like' : 'Comment'); } else { - + $tpl = get_markup_template('diaspora_signed_retract.tpl'); $target_type = 'StatusMessage'; } @@ -2644,8 +2997,8 @@ function diaspora_send_mail($item,$owner,$contact) { $body = bb2diaspora($item['body']); $created = datetime_convert('UTC','UTC',$item['created'],'Y-m-d H:i:s \U\T\C'); - - $signed_text = $item['guid'] . ';' . $cnv['guid'] . ';' . $body . ';' + + $signed_text = $item['guid'] . ';' . $cnv['guid'] . ';' . $body . ';' . $created . ';' . $myaddr . ';' . $cnv['guid']; $sig = base64_encode(rsa_sign($signed_text,$owner['uprvkey'],'sha256')); @@ -2653,7 +3006,7 @@ function diaspora_send_mail($item,$owner,$contact) { $msg = array( 'guid' => xmlify($item['guid']), 'parent_guid' => xmlify($cnv['guid']), - 'parent_author_signature' => (($item['reply']) ? null : xmlify($sig)), + 'parent_author_signature' => xmlify($sig), 'author_signature' => xmlify($sig), 'text' => xmlify($body), 'created_at' => xmlify($created), @@ -2735,4 +3088,46 @@ function diaspora_transmit($owner,$contact,$slap,$public_batch,$queue_run=false) return(($return_code) ? $return_code : (-1)); } +function diaspora_fetch_relay() { + + $serverdata = get_config("system", "relay_server"); + if ($serverdata == "") + return array(); + $relay = array(); + + $servers = explode(",", $serverdata); + + foreach($servers AS $server) { + $server = trim($server); + $batch = $server."/receive/public"; + + $relais = q("SELECT `batch`, `id`, `name`,`network` FROM `contact` WHERE `uid` = 0 AND `batch` = '%s' LIMIT 1", dbesc($batch)); + + if (!$relais) { + $addr = "relay@".str_replace("http://", "", normalise_link($server)); + + $r = q("INSERT INTO `contact` (`uid`, `created`, `name`, `nick`, `addr`, `url`, `nurl`, `batch`, `network`, `rel`, `blocked`, `pending`, `writable`, `name-date`, `uri-date`, `avatar-date`) + VALUES (0, '%s', '%s', 'relay', '%s', '%s', '%s', '%s', '%s', %d, 0, 0, 1, '%s', '%s', '%s')", + datetime_convert(), + dbesc($addr), + dbesc($addr), + dbesc($server), + dbesc(normalise_link($server)), + dbesc($batch), + dbesc(NETWORK_DIASPORA), + intval(CONTACT_IS_FOLLOWER), + dbesc(datetime_convert()), + dbesc(datetime_convert()), + dbesc(datetime_convert()) + ); + + $relais = q("SELECT `batch`, `id`, `name`,`network` FROM `contact` WHERE `uid` = 0 AND `batch` = '%s' LIMIT 1", dbesc($batch)); + if ($relais) + $relay[] = $relais[0]; + } else + $relay[] = $relais[0]; + } + + return $relay; +}