X-Git-Url: https://git.mxchange.org/?a=blobdiff_plain;f=include%2Fdiaspora.php;h=93fe2a472feb47268375709fd4f771614c8e7634;hb=a3c79d2007884b2057db6279be011e2db6b6cdbe;hp=b70cffdc39efebd8cf0073887301a8891653a387;hpb=9a22b4818e0a406c89ff1cc84be4232c8a979f78;p=friendica.git diff --git a/include/diaspora.php b/include/diaspora.php old mode 100755 new mode 100644 index b70cffdc39..93fe2a472f --- a/include/diaspora.php +++ b/include/diaspora.php @@ -1,5 +1,11 @@ 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']) ); @@ -30,7 +43,7 @@ function diaspora_dispatch_public($msg) { } } else - logger('diaspora_public: no subscribers'); + logger('diaspora_public: no subscribers for '.$msg["author"].' '.print_r($msg, true)); } @@ -99,6 +112,9 @@ function diaspora_dispatch($importer,$msg,$attempt=1) { elseif($xmlbase->message) { $ret = diaspora_message($importer,$xmlbase->message,$msg); } + elseif($xmlbase->participation) { + $ret = diaspora_participation($importer,$xmlbase->participation); + } else { logger('diaspora_dispatch: unknown message type: ' . print_r($xmlbase,true)); } @@ -540,7 +556,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.'); @@ -578,7 +594,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_FREELOVE))) { q("UPDATE `contact` SET `rel` = %d, `writable` = 1 WHERE `id` = %d AND `uid` = %d", intval(CONTACT_IS_FRIEND), intval($contact['id']), @@ -635,7 +651,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 +729,7 @@ function diaspora_request($importer,$xml) { require_once('include/Photo.php'); - $photos = import_profile_photo($contact_record['photo'],$importer['uid'],$contact_record['id']); + update_contact_avatar($contact_record['photo'],$importer['uid'],$contact_record['id']); // technically they are sharing with us (CONTACT_IS_SHARING), // but if our page-type is PAGE_COMMUNITY or PAGE_SOAPBOX @@ -724,26 +740,17 @@ function diaspora_request($importer,$xml) { else $new_relation = CONTACT_IS_FOLLOWER; - $r = q("UPDATE `contact` SET - `photo` = '%s', - `thumb` = '%s', - `micro` = '%s', - `rel` = %d, + $r = q("UPDATE `contact` SET `rel` = %d, `name-date` = '%s', `uri-date` = '%s', - `avatar-date` = '%s', `blocked` = 0, `pending` = 0, `writable` = 1 WHERE `id` = %d ", - dbesc($photos[0]), - dbesc($photos[1]), - dbesc($photos[2]), intval($new_relation), dbesc(datetime_convert()), dbesc(datetime_convert()), - dbesc(datetime_convert()), intval($contact_record['id']) ); @@ -755,12 +762,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_FREELOVE))) { q("UPDATE `contact` SET `rel` = %d, `writable` = 1 WHERE `id` = %d AND `uid` = %d", intval(CONTACT_IS_FRIEND), intval($contact['id']), @@ -775,8 +782,13 @@ 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; } @@ -785,7 +797,7 @@ function diaspora_is_redmatrix($url) { } function diaspora_plink($addr, $guid) { - $r = q("SELECT `url`, `nick`, `network` FROM `fcontact` WHERE `addr`='%s' LIMIT 1", $addr); + $r = q("SELECT `url`, `nick`, `network` FROM `fcontact` WHERE `addr`='%s' LIMIT 1", dbesc($addr)); // Fallback if (!$r) @@ -806,6 +818,23 @@ function diaspora_plink($addr, $guid) { return 'https://'.substr($addr,strpos($addr,'@')+1).'/posts/'.$guid; } +function diaspora_repair_signature($signature, $handle = "", $level = 1) { + + if ($signature == "") + return($signature); + + if (base64_encode(base64_decode(base64_decode($signature))) == base64_decode($signature)) { + $signature = base64_decode($signature); + logger("Repaired double encoded signature from Diaspora/Hubzilla handle ".$handle." - level ".$level, LOGGER_DEBUG); + + // Do a recursive call to be able to fix even multiple levels + if ($level < 10) + $signature = diaspora_repair_signature($signature, $handle, ++$level); + } + + return($signature); +} + function diaspora_post($importer,$xml,$msg) { $a = get_app(); @@ -818,23 +847,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; + return 208; } $created = unxmlify($xml->created_at); @@ -889,7 +919,7 @@ function diaspora_post($importer,$xml,$msg) { $datarray['body'] = $body; $datarray['tag'] = $str_tags; if ($xml->provider_display_name) - $datarray["app"] = unxmlify($xml->provider_display_name); + $datarray["app"] = unxmlify($xml->provider_display_name); else $datarray['app'] = 'Diaspora'; @@ -900,7 +930,9 @@ function diaspora_post($importer,$xml,$msg) { DiasporaFetchGuid($datarray); $message_id = item_store($datarray); - return; + logger("Stored item with message id ".$message_id, LOGGER_DEBUG); + + return 201; } @@ -921,8 +953,8 @@ function DiasporaFetchGuidSub($match, $item) { function diaspora_store_by_guid($guid, $server, $uid = 0) { require_once("include/Contact.php"); - $serverparts = parse_url($server); - $server = $serverparts["scheme"]."://".$serverparts["host"]; + $serverparts = parse_url($server); + $server = $serverparts["scheme"]."://".$serverparts["host"]; logger("Trying to fetch item ".$guid." from ".$server, LOGGER_DEBUG); @@ -944,9 +976,8 @@ function diaspora_store_by_guid($guid, $server, $uid = 0) { $objecttype = $item["object-type"]; $message_id = $author.':'.$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($uid), - dbesc($message_id), dbesc($guid) ); if(count($r)) @@ -954,9 +985,21 @@ function diaspora_store_by_guid($guid, $server, $uid = 0) { $person = find_diaspora_person_by_handle($author); - $datarray = array(); + $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'] = get_contact($person['url'], $uid); + $datarray['contact-id'] = $contact_id; $datarray['wall'] = 0; $datarray['network'] = NETWORK_DIASPORA; $datarray['guid'] = $guid; @@ -984,8 +1027,8 @@ function diaspora_store_by_guid($guid, $server, $uid = 0) { 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 + /// @TODO + /// Looking if there is some subscribe mechanism in Diaspora to get all comments for this post return $message_id; } @@ -1055,8 +1098,8 @@ function diaspora_fetch_message($guid, $server, $level = 0) { $body = scale_external_images($body); // Add OEmbed and other information to the body - // To-Do: It could be a repeated redmatrix item - // Then we shouldn't add further data to it + /// @TODO 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); @@ -1096,15 +1139,14 @@ function diaspora_reshare($importer,$xml,$msg) { if(! $contact) return; - if(! diaspora_post_allow($importer,$contact)) { + 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 `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)) { @@ -1282,15 +1324,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)) { @@ -1355,11 +1396,6 @@ function diaspora_asphoto($importer,$xml,$msg) { } - - - - - function diaspora_comment($importer,$xml,$msg) { $a = get_app(); @@ -1378,7 +1414,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; } @@ -1479,16 +1515,27 @@ function diaspora_comment($importer,$xml,$msg) { } } + // Fetch the contact id - if we know this contact + $r = q("SELECT `id`, `network` FROM `contact` WHERE `nurl` = '%s' AND `uid` = %d LIMIT 1", + dbesc(normalise_link($person['url'])), intval($importer['uid'])); + if ($r) { + $cid = $r[0]['id']; + $network = $r[0]['network']; + } else { + $cid = $contact['id']; + $network = NETWORK_DIASPORA; + } + $body = diaspora2bb($text); $message_id = $diaspora_handle . ':' . $guid; $datarray = array(); $datarray['uid'] = $importer['uid']; - $datarray['contact-id'] = $contact['id']; + $datarray['contact-id'] = $cid; $datarray['type'] = 'remote-comment'; $datarray['wall'] = $parent_item['wall']; - $datarray['network'] = NETWORK_DIASPORA; + $datarray['network'] = $network; $datarray['verb'] = ACTIVITY_POST; $datarray['gravity'] = GRAVITY_COMMENT; $datarray['guid'] = $guid; @@ -1527,62 +1574,22 @@ function diaspora_comment($importer,$xml,$msg) { //); //} - if(($parent_item['origin']) && (! $parent_author_signature)) { + // If we are the origin of the parent we store the original signature and notify our followers + if($parent_item['origin']) { + $author_signature_base64 = base64_encode($author_signature); + $author_signature_base64 = diaspora_repair_signature($author_signature_base64, $diaspora_handle); + q("insert into sign (`iid`,`signed_text`,`signature`,`signer`) values (%d,'%s','%s','%s') ", intval($message_id), dbesc($signed_data), - dbesc(base64_encode($author_signature)), + dbesc($author_signature_base64), dbesc($diaspora_handle) ); - // if the message isn't already being relayed, notify others - // the existence of parent_author_signature means the parent_author or owner - // is already relaying. - + // notify others proc_run('php','include/notifier.php','comment-import',$message_id); } - $myconv = q("SELECT `author-link`, `author-avatar`, `parent` FROM `item` WHERE `parent-uri` = '%s' AND `uid` = %d AND `parent` != 0 AND `deleted` = 0 ", - dbesc($parent_item['uri']), - intval($importer['uid']) - ); - - if(count($myconv)) { - $importer_url = $a->get_baseurl() . '/profile/' . $importer['nickname']; - - foreach($myconv as $conv) { - - // now if we find a match, it means we're in this conversation - - if(! link_compare($conv['author-link'],$importer_url)) - continue; - - require_once('include/enotify.php'); - - $conv_parent = $conv['parent']; - - notification(array( - 'type' => NOTIFY_COMMENT, - 'notify_flags' => $importer['notify-flags'], - 'language' => $importer['language'], - 'to_name' => $importer['username'], - 'to_email' => $importer['email'], - 'uid' => $importer['uid'], - 'item' => $datarray, - 'link' => $a->get_baseurl().'/display/'.urlencode($datarray['guid']), - 'source_name' => $datarray['author-name'], - 'source_link' => $datarray['author-link'], - 'source_photo' => $datarray['author-avatar'], - 'verb' => ACTIVITY_POST, - 'otype' => 'item', - 'parent' => $conv_parent, - 'parent_uri' => $parent_uri - )); - - // only send one notification - break; - } - } return; } @@ -1600,7 +1607,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)) { @@ -1614,7 +1621,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; } @@ -1639,11 +1646,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.'); @@ -1737,7 +1744,6 @@ function diaspora_conversation($importer,$xml,$msg) { intval($conversation['id']) ); - require_once('include/enotify.php'); notification(array( 'type' => NOTIFY_MAIL, 'notify_flags' => $importer['notify-flags'], @@ -1770,15 +1776,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; } @@ -1806,7 +1812,7 @@ function diaspora_message($importer,$xml,$msg) { $author_signature = base64_decode($msg_author_signature); - $person = find_diaspora_person_by_handle($msg_diaspora_handle); + $person = find_diaspora_person_by_handle($msg_diaspora_handle); if(is_array($person) && x($person,'pubkey')) $key = $person['pubkey']; else { @@ -1853,6 +1859,9 @@ function diaspora_message($importer,$xml,$msg) { return; } +function diaspora_participation($importer,$xml) { + logger("Unsupported message type 'participation' ".print_r($xml, true)); +} function diaspora_photo($importer,$xml,$msg,$attempt=1) { @@ -1882,7 +1891,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; } @@ -1929,14 +1938,18 @@ 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) { + + $parent_item['body'] = $link_text . $parent_item['body']; + $r = q("UPDATE `item` SET `body` = '%s', `visible` = 1 WHERE `id` = %d AND `uid` = %d", - dbesc($link_text . $parent_item['body']), + dbesc($parent_item['body']), intval($parent_item['id']), intval($parent_item['uid']) ); + put_item_in_cache($parent_item, true); update_thread($parent_item['id']); } @@ -1969,7 +1982,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; } @@ -2121,13 +2134,24 @@ function diaspora_like($importer,$xml,$msg) { EOT; $bodyverb = t('%1$s likes %2$s\'s %3$s'); + // Fetch the contact id - if we know this contact + $r = q("SELECT `id`, `network` FROM `contact` WHERE `nurl` = '%s' AND `uid` = %d LIMIT 1", + dbesc(normalise_link($person['url'])), intval($importer['uid'])); + if ($r) { + $cid = $r[0]['id']; + $network = $r[0]['network']; + } else { + $cid = $contact['id']; + $network = NETWORK_DIASPORA; + } + $arr = array(); $arr['uri'] = $uri; $arr['uid'] = $importer['uid']; $arr['guid'] = $guid; - $arr['network'] = NETWORK_DIASPORA; - $arr['contact-id'] = $contact['id']; + $arr['network'] = $network; + $arr['contact-id'] = $cid; $arr['type'] = 'activity'; $arr['wall'] = $parent_item['wall']; $arr['gravity'] = GRAVITY_LIKE; @@ -2170,21 +2194,21 @@ EOT; // ); //} - if(! $parent_author_signature) { + // If we are the origin of the parent we store the original signature and notify our followers + if($parent_item['origin']) { + $author_signature_base64 = base64_encode($author_signature); + $author_signature_base64 = diaspora_repair_signature($author_signature_base64, $diaspora_handle); + q("insert into sign (`iid`,`signed_text`,`signature`,`signer`) values (%d,'%s','%s','%s') ", intval($message_id), dbesc($signed_data), - dbesc(base64_encode($author_signature)), + dbesc($author_signature_base64), dbesc($diaspora_handle) ); - } - - // if the message isn't already being relayed, notify others - // the existence of parent_author_signature means the parent_author or owner - // is already relaying. The parent_item['origin'] indicates the message was created on our system - if(($parent_item['origin']) && (! $parent_author_signature)) + // notify others proc_run('php','include/notifier.php','comment-import',$message_id); + } return; } @@ -2203,8 +2227,23 @@ function diaspora_retraction($importer,$xml) { if($type === 'Person') { require_once('include/Contact.php'); contact_remove($contact['id']); - } - elseif($type === 'Post') { + } elseif($type === 'StatusMessage') { + $guid = notags(unxmlify($xml->post_guid)); + + $r = q("SELECT * FROM `item` WHERE `guid` = '%s' AND `uid` = %d AND NOT `file` LIKE '%%[%%' LIMIT 1", + dbesc($guid), + intval($importer['uid']) + ); + if(count($r)) { + if(link_compare($r[0]['author-link'],$contact['url'])) { + q("UPDATE `item` SET `deleted` = 1, `changed` = '%s' WHERE `id` = %d", + dbesc(datetime_convert()), + intval($r[0]['id']) + ); + delete_thread($r[0]['id'], $r[0]['parent-uri']); + } + } + } elseif($type === 'Post') { $r = q("select * from item where guid = '%s' and uid = %d and not file like '%%[%%' limit 1", dbesc('guid'), intval($importer['uid']) @@ -2265,8 +2304,7 @@ function diaspora_signed_retraction($importer,$xml,$msg) { return; } - } - else { + } else { $sig_decode = base64_decode($sig); @@ -2295,12 +2333,12 @@ function diaspora_signed_retraction($importer,$xml,$msg) { // The first item in the `item` table with the parent id is the parent. However, MySQL doesn't always // return the items ordered by `item`.`id`, in which case the wrong item is chosen as the parent. // The only item with `parent` and `id` as the parent id is the parent item. - $p = q("select origin from item where parent = %d and id = %d limit 1", - $r[0]['parent'], - $r[0]['parent'] + $p = q("SELECT `origin` FROM `item` WHERE `parent` = %d AND `id` = %d LIMIT 1", + intval($r[0]['parent']), + intval($r[0]['parent']) ); if(count($p)) { - if(($p[0]['origin']) && (! $parent_author_signature)) { + if($p[0]['origin']) { q("insert into sign (`retract_iid`,`signed_text`,`signature`,`signer`) values (%d,'%s','%s','%s') ", $r[0]['id'], dbesc($signed_data), @@ -2340,10 +2378,10 @@ function diaspora_profile($importer,$xml,$msg) { if(! $contact) return; - if($contact['blocked']) { - logger('diaspora_post: Ignoring this author.'); - return 202; - } + //if($contact['blocked']) { + // logger('diaspora_post: Ignoring this author.'); + // return 202; + //} $name = unxmlify($xml->first_name) . ((strlen($xml->last_name)) ? ' ' . unxmlify($xml->last_name) : ''); $image_url = unxmlify($xml->image_url); @@ -2351,6 +2389,8 @@ function diaspora_profile($importer,$xml,$msg) { $location = diaspora2bb(unxmlify($xml->location)); $about = diaspora2bb(unxmlify($xml->bio)); $gender = unxmlify($xml->gender); + $searchable = (unxmlify($xml->searchable) == "true"); + $nsfw = (unxmlify($xml->nsfw) == "true"); $tags = unxmlify($xml->tag_string); $tags = explode("#", $tags); @@ -2365,6 +2405,8 @@ function diaspora_profile($importer,$xml,$msg) { $keywords = implode(", ", $keywords); $handle_parts = explode("@", $diaspora_handle); + $nick = $handle_parts[0]; + if($name === '') { $name = $handle_parts[0]; } @@ -2381,13 +2423,14 @@ function diaspora_profile($importer,$xml,$msg) { require_once('include/Photo.php'); - $images = import_profile_photo($image_url,$importer['uid'],$contact['id']); + update_contact_avatar($image_url,$importer['uid'],$contact['id']); // Generic birthday. We don't know the timezone. The year is irrelevant. $birthday = str_replace('1000','1901',$birthday); - $birthday = datetime_convert('UTC','UTC',$birthday,'Y-m-d'); + if ($birthday != "") + $birthday = datetime_convert('UTC','UTC',$birthday,'Y-m-d'); // this is to prevent multiple birthday notifications in a single year // if we already have a stored birthday and the 'm-d' part hasn't changed, preserve the entry, which will preserve the notify year @@ -2395,15 +2438,14 @@ function diaspora_profile($importer,$xml,$msg) { if(substr($birthday,5) === substr($contact['bd'],5)) $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. + /// @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). - $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", + $r = q("UPDATE `contact` SET `name` = '%s', `nick` = '%s', `addr` = '%s', `name-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]), - dbesc($images[1]), - dbesc($images[2]), + dbesc($nick), + dbesc($diaspora_handle), dbesc(datetime_convert()), dbesc($birthday), dbesc($location), @@ -2414,26 +2456,17 @@ function diaspora_profile($importer,$xml,$msg) { intval($importer['uid']) ); - if (unxmlify($xml->searchable) == "true") { + if ($searchable) { require_once('include/socgraph.php'); - poco_check($contact['url'], $name, NETWORK_DIASPORA, $images[0], $about, $location, $gender, $keywords, "", + poco_check($contact['url'], $name, NETWORK_DIASPORA, $image_url, $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']))); - } + update_gcontact(array("url" => $contact['url'], "network" => NETWORK_DIASPORA, "generation" => 2, + "photo" => $image_url, "name" => $name, "location" => $location, + "about" => $about, "birthday" => $birthday, "gender" => $gender, + "addr" => $diaspora_handle, "nick" => $nick, "keywords" => $keywords, + "hide" => !$searchable, "nsfw" => $nsfw)); /* if($r) { if($oldphotos) { @@ -2575,11 +2608,12 @@ function diaspora_send_status($item,$owner,$contact,$public_batch = false) { } logger('diaspora_send_status: '.$owner['username'].' -> '.$contact['name'].' base message: '.$msg, LOGGER_DATA); + logger('send guid '.$item['guid'], LOGGER_DEBUG); $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); + $return_code = diaspora_transmit($owner,$contact,$slap,$public_batch,false,$item['guid']); logger('diaspora_send_status: guid: '.$item['guid'].' result '.$return_code, LOGGER_DEBUG); @@ -2593,28 +2627,28 @@ function diaspora_send_status($item,$owner,$contact,$public_batch = false) { 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); + // 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); + // 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); + $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]; + $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]; + 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", @@ -2627,35 +2661,35 @@ function diaspora_is_reshare($body) { } } - $profile = ""; - preg_match("/profile='(.*?)'/ism", $attributes, $matches); - if ($matches[1] != "") - $profile = $matches[1]; + $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]; + preg_match('/profile="(.*?)"/ism', $attributes, $matches); + if ($matches[1] != "") + $profile = $matches[1]; - $ret= array(); + $ret= array(); - $ret["root_handle"] = preg_replace("=https?://(.*)/u/(.*)=ism", "$2@$1", $profile); - if (($ret["root_handle"] == $profile) OR ($ret["root_handle"] == "")) - return(false); + $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]; + $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]; + 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); + $ret["root_guid"] = preg_replace("=https?://(.*)/posts/(.*)=ism", "$2", $link); + if (($ret["root_guid"] == $link) OR ($ret["root_guid"] == "")) + return(false); - return($ret); + return($ret); } function diaspora_send_images($item,$owner,$contact,$images,$public_batch = false) { @@ -2690,10 +2724,12 @@ function diaspora_send_images($item,$owner,$contact,$images,$public_batch = fals logger('diaspora_send_photo: base message: ' . $msg, LOGGER_DATA); + logger('send guid '.$r[0]['guid'], LOGGER_DEBUG); + $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)); - diaspora_transmit($owner,$contact,$slap,$public_batch); + diaspora_transmit($owner,$contact,$slap,$public_batch,false,$r[0]['guid']); } } @@ -2709,7 +2745,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 { @@ -2747,7 +2783,7 @@ function diaspora_send_followup($item,$owner,$contact,$public_batch = false) { // sign it if($like) - $signed_text = $item['guid'] . ';' . $target_type . ';' . $parent['guid'] . ';' . $positive . ';' . $myaddr; + $signed_text = $positive . ';' . $item['guid'] . ';' . $target_type . ';' . $parent['guid'] . ';' . $myaddr; else $signed_text = $item['guid'] . ';' . $parent['guid'] . ';' . $text . ';' . $myaddr; @@ -2764,11 +2800,12 @@ function diaspora_send_followup($item,$owner,$contact,$public_batch = false) { )); logger('diaspora_followup: base message: ' . $msg, LOGGER_DATA); + logger('send guid '.$item['guid'], LOGGER_DEBUG); $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(diaspora_transmit($owner,$contact,$slap,$public_batch)); + return(diaspora_transmit($owner,$contact,$slap,$public_batch,false,$item['guid'])); } @@ -2779,15 +2816,12 @@ function diaspora_send_relay($item,$owner,$contact,$public_batch = false) { $myaddr = $owner['nickname'] . '@' . substr($a->get_baseurl(), strpos($a->get_baseurl(),'://') + 3); // $theiraddr = $contact['addr']; - $body = $item['body']; - $text = html_entity_decode(bb2diaspora($body)); - // Diaspora doesn't support threaded comments, but some // versions of Diaspora (i.e. Diaspora-pistos) support // 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 { @@ -2832,61 +2866,53 @@ function diaspora_send_relay($item,$owner,$contact,$public_batch = false) { // fetch the original signature if the relayable was created by a Diaspora // or DFRN user. Relayables for other networks are not supported. -/* $r = q("select * from sign where " . $sql_sign_id . " = %d limit 1", + $r = q("SELECT `signed_text`, `signature`, `signer` FROM `sign` WHERE " . $sql_sign_id . " = %d LIMIT 1", intval($item['id']) ); - if(count($r)) { + if(count($r)) { $orig_sign = $r[0]; $signed_text = $orig_sign['signed_text']; $authorsig = $orig_sign['signature']; $handle = $orig_sign['signer']; + + // Split the signed text + $signed_parts = explode(";", $signed_text); + + // Remove the parent guid + array_shift($signed_parts); + + // Remove the comment guid + array_shift($signed_parts); + + // Remove the handle + array_pop($signed_parts); + + // Glue the parts together + $text = implode(";", $signed_parts); } else { + // This part is meant for cases where we don't have the signatur. (Which shouldn't happen with posts from Diaspora and Friendica) + // This means that the comment won't be accepted by newer Diaspora servers - // Author signature information (for likes, comments, and retractions of likes or comments, - // whether from Diaspora or Friendica) must be placed in the `sign` table before this - // function is called - logger('diaspora_send_relay: original author signature not found, cannot send relayable'); - return; - }*/ - - /* Since the author signature is only checked by the parent, not by the relay recipients, - * I think it may not be necessary for us to do so much work to preserve all the original - * signatures. The important thing that Diaspora DOES need is the original creator's handle. - * Let's just generate that and forget about all the original author signature stuff. - * - * Note: this might be more of an problem if we want to support likes on comments for older - * versions of Diaspora (diaspora-pistos), but since there are a number of problems with - * doing that, let's ignore it for now. - * - * Currently, only DFRN contacts are supported. StatusNet shouldn't be hard, but it hasn't - * been done yet - */ - - $handle = diaspora_handle_from_contact($item['contact-id']); - if(! $handle) - return; + $body = $item['body']; + $text = html_entity_decode(bb2diaspora($body)); + $handle = diaspora_handle_from_contact($item['contact-id']); + if(! $handle) + return; - if($relay_retract) - $sender_signed_text = $item['guid'] . ';' . $target_type; - elseif($like) - $sender_signed_text = $item['guid'] . ';' . $target_type . ';' . $parent['guid'] . ';' . $positive . ';' . $handle; - else - $sender_signed_text = $item['guid'] . ';' . $parent['guid'] . ';' . $text . ';' . $handle; + if($relay_retract) + $signed_text = $item['guid'] . ';' . $target_type; + elseif($like) + $signed_text = $item['guid'] . ';' . $target_type . ';' . $parent['guid'] . ';' . $positive . ';' . $handle; + else + $signed_text = $item['guid'] . ';' . $parent['guid'] . ';' . $text . ';' . $handle; - // Sign the relayable with the top-level owner's signature - // - // We'll use the $sender_signed_text that we just created, instead of the $signed_text - // stored in the database, because that provides the best chance that Diaspora will - // be able to reconstruct the signed text the same way we did. This is particularly a - // concern for the comment, whose signed text includes the text of the comment. The - // smallest change in the text of the comment, including removing whitespace, will - // make the signature verification fail. Since we translate from BB code to Diaspora's - // markup at the top of this function, which is AFTER we placed the original $signed_text - // in the database, it's hazardous to trust the original $signed_text. + $authorsig = base64_encode(rsa_sign($signed_text,$owner['uprvkey'],'sha256')); + } - $parentauthorsig = base64_encode(rsa_sign($sender_signed_text,$owner['uprvkey'],'sha256')); + // Sign the relayable with the top-level owner's signature + $parentauthorsig = base64_encode(rsa_sign($signed_text,$owner['uprvkey'],'sha256')); $msg = replace_macros($tpl,array( '$guid' => xmlify($item['guid']), @@ -2900,12 +2926,12 @@ function diaspora_send_relay($item,$owner,$contact,$public_batch = false) { )); logger('diaspora_send_relay: base message: ' . $msg, LOGGER_DATA); - + logger('send guid '.$item['guid'], LOGGER_DEBUG); $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(diaspora_transmit($owner,$contact,$slap,$public_batch)); + return(diaspora_transmit($owner,$contact,$slap,$public_batch,false,$item['guid'])); } @@ -2937,10 +2963,12 @@ function diaspora_send_retraction($item,$owner,$contact,$public_batch = false) { '$signature' => xmlify(base64_encode(rsa_sign($signed_text,$owner['uprvkey'],'sha256'))) )); + logger('send guid '.$item['guid'], LOGGER_DEBUG); + $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(diaspora_transmit($owner,$contact,$slap,$public_batch)); + return(diaspora_transmit($owner,$contact,$slap,$public_batch,false,$item['guid'])); } function diaspora_send_mail($item,$owner,$contact) { @@ -2970,7 +2998,7 @@ 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')); @@ -2978,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), @@ -2997,16 +3025,17 @@ function diaspora_send_mail($item,$owner,$contact) { } logger('diaspora_conversation: ' . print_r($xmsg,true), LOGGER_DATA); + logger('send guid '.$item['guid'], LOGGER_DEBUG); $slap = 'xml=' . urlencode(urlencode(diaspora_msg_build($xmsg,$owner,$contact,$owner['uprvkey'],$contact['pubkey'],false))); //$slap = 'xml=' . urlencode(diaspora_msg_build($xmsg,$owner,$contact,$owner['uprvkey'],$contact['pubkey'],false)); - return(diaspora_transmit($owner,$contact,$slap,false)); + return(diaspora_transmit($owner,$contact,$slap,false,false,$item['guid'])); } -function diaspora_transmit($owner,$contact,$slap,$public_batch,$queue_run=false) { +function diaspora_transmit($owner,$contact,$slap,$public_batch,$queue_run=false,$guid = "") { $enabled = intval(get_config('system','diaspora_enabled')); if(! $enabled) { @@ -3019,9 +3048,9 @@ function diaspora_transmit($owner,$contact,$slap,$public_batch,$queue_run=false) if(! $dest_url) { logger('diaspora_transmit: no url for contact: ' . $contact['id'] . ' batch mode =' . $public_batch); return 0; - } + } - logger('diaspora_transmit: ' . $logid . ' ' . $dest_url); + logger('diaspora_transmit: '.$logid.'-'.$guid.' '.$dest_url); if( (! $queue_run) && (was_recently_delayed($contact['id'])) ) { $return_code = 0; @@ -3036,7 +3065,7 @@ function diaspora_transmit($owner,$contact,$slap,$public_batch,$queue_run=false) } } - logger('diaspora_transmit: ' . $logid . ' returns: ' . $return_code); + logger('diaspora_transmit: '.$logid.'-'.$guid.' returns: '.$return_code); if((! $return_code) || (($return_code == 503) && (stristr($a->get_curl_headers(),'retry-after')))) { logger('diaspora_transmit: queue message'); @@ -3059,3 +3088,47 @@ 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; +}