X-Git-Url: https://git.mxchange.org/?a=blobdiff_plain;f=include%2Fdiaspora.php;h=10b342289719789bb13ed1aa643b88ca81151e55;hb=030dcbd467d5faf01e6f62b9cd9b1be6f8974dcc;hp=4113e9ce10b4b14bfe5041bf64b93c473c6b5867;hpb=812222fb1757c046b80a7b8169d69626256098cf;p=friendica.git diff --git a/include/diaspora.php b/include/diaspora.php index 4113e9ce10..10b3422897 100644 --- a/include/diaspora.php +++ b/include/diaspora.php @@ -2,6 +2,75 @@ require_once('include/crypto.php'); require_once('include/items.php'); +require_once('include/bb2diaspora.php'); +require_once('include/contact_selectors.php'); + +function diaspora_dispatch($importer,$msg) { + + $parsed_xml = parse_xml_string($msg['message'],false); + + $xmlbase = $parsed_xml->post; + + if($xmlbase->request) { + diaspora_request($importer,$xmlbase->request); + } + elseif($xmlbase->status_message) { + diaspora_post($importer,$xmlbase->status_message); + } + elseif($xmlbase->comment) { + diaspora_comment($importer,$xmlbase->comment,$msg); + } + elseif($xmlbase->like) { + diaspora_like($importer,$xmlbase->like,$msg); + } + elseif($xmlbase->retraction) { + diaspora_retraction($importer,$xmlbase->retraction,$msg); + } + elseif($xmlbase->photo) { + diaspora_photo($importer,$xmlbase->photo,$msg); + } + else { + logger('diaspora_dispatch: unknown message type: ' . print_r($xmlbase,true)); + } + return; +} + +function diaspora_get_contact_by_handle($uid,$handle) { + $r = q("SELECT * FROM `contact` WHERE `network` = '%s' AND `uid` = %d AND `addr` = '%s' LIMIT 1", + dbesc(NETWORK_DIASPORA), + intval($uid), + dbesc($handle) + ); + if($r && count($r)) + return $r[0]; + return false; +} + +function find_diaspora_person_by_handle($handle) { + $r = q("select * from fcontact where network = '%s' and addr = '%s' limit 1", + dbesc(NETWORK_DIASPORA), + dbesc($handle) + ); + if(count($r)) { + // update record occasionally so it doesn't get stale + $d = strtotime($r[0]['updated'] . ' +00:00'); + if($d < strtotime('now - 14 days')) { + q("delete from fcontact where id = %d limit 1", + intval($r[0]['id']) + ); + } + else + return $r[0]; + } + require_once('include/Scrape.php'); + $r = probe_url($handle, PROBE_DIASPORA); + if((count($r)) && ($r['network'] === NETWORK_DIASPORA)) { + add_fcontact($r); + return ($r); + } + return false; +} + function get_diaspora_key($uri) { logger('Fetching diaspora key for: ' . $uri); @@ -13,16 +82,6 @@ function get_diaspora_key($uri) { } -function diaspora_base_message($type,$data) { - - $tpl = get_markup_template('diaspora_' . $type . '.tpl'); - if(! $tpl) - return ''; - return replace_macros($tpl,$data); - -} - - function diaspora_msg_build($msg,$user,$contact,$prvkey,$pubkey) { $a = get_app(); @@ -77,10 +136,15 @@ EOT; $ciphertext = mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $outer_aes_key, $decrypted_header, MCRYPT_MODE_CBC, $outer_iv); $outer_json = json_encode(array('iv' => $b_outer_iv,'key' => $b_outer_aes_key)); + $encrypted_outer_key_bundle = ''; openssl_public_encrypt($outer_json,$encrypted_outer_key_bundle,$pubkey); - + + logger('outer_bundle_encrypt: ' . openssl_error_string()); $b64_encrypted_outer_key_bundle = base64_encode($encrypted_outer_key_bundle); + + logger('outer_bundle: ' . $b64_encrypted_outer_key_bundle . ' key: ' . $pubkey); + $encrypted_header_json_object = json_encode(array('aes_key' => base64_encode($encrypted_outer_key_bundle), 'ciphertext' => base64_encode($ciphertext))); $cipher_json = base64_encode($encrypted_header_json_object); @@ -257,42 +321,6 @@ function diaspora_decode($importer,$xml) { } -function diaspora_get_contact_by_handle($uid,$handle) { - $r = q("SELECT * FROM `contact` WHERE `network` = '%s' AND `uid` = %d AND `addr` = '%s' LIMIT 1", - dbesc(NETWORK_DIASPORA), - intval($uid), - dbesc($handle) - ); - if($r && count($r)) - return $r[0]; - return false; -} - -function find_diaspora_person_by_handle($handle) { - $r = q("select * from fcontact where network = '%s' and addr = '%s' limit 1", - dbesc(NETWORK_DIASPORA), - dbesc($handle) - ); - if(count($r)) { - // update record occasionally so it doesn't get stale - $d = strtotime($r[0]['updated'] . ' +00:00'); - if($d < strtotime('now - 14 days')) { - q("delete from fcontact where id = %d limit 1", - intval($r[0]['id']) - ); - } - else - return $r[0]; - } - require_once('include/Scrape.php'); - $r = probe_url($handle, PROBE_DIASPORA); - if((count($r)) && ($r['network'] === NETWORK_DIASPORA)) { - add_fcontact($r); - return ($r); - } - return false; -} - function diaspora_request($importer,$xml) { @@ -408,32 +436,7 @@ function diaspora_post($importer,$xml) { $created = unxmlify($xml->created_at); $private = ((unxmlify($xml->public) == 'false') ? 1 : 0); - $body = unxmlify($xml->raw_message); - - require_once('library/HTMLPurifier.auto.php'); - require_once('include/html2bbcode.php'); - - $maxlen = get_max_import_size(); - if($maxlen && (strlen($body) > $maxlen)) - $body = substr($body,0, $maxlen); - - if((strpos($body,'<') !== false) || (strpos($body,'>') !== false)) { - - $body = preg_replace('#]+>.+?' . 'http://www.youtube.com/((?:v|cp)/[A-Za-z0-9\-_=]+).+?#s', - '[youtube]$1[/youtube]', $body); - - $body = preg_replace('#].+?' . 'http://www.youtube.com/embed/([A-Za-z0-9\-_=]+).+?#s', - '[youtube]$1[/youtube]', $body); - - $body = oembed_html2bbcode($body); - - $config = HTMLPurifier_Config::createDefault(); - $config->set('Cache.DefinitionImpl', null); - $purifier = new HTMLPurifier($config); - $body = $purifier->purify($body); - - $body = html2bbcode($body); - } + $body = diaspora2bb($xml->raw_message); $datarray = array(); $datarray['uid'] = $importer['uid']; @@ -451,6 +454,7 @@ function diaspora_post($importer,$xml) { $datarray['author-link'] = $contact['url']; $datarray['author-avatar'] = $contact['thumb']; $datarray['body'] = $body; + $datarray['app'] = 'Diaspora'; item_store($datarray); @@ -481,6 +485,15 @@ function diaspora_comment($importer,$xml,$msg) { // NOTREACHED } + $r = q("SELECT * FROM `item` WHERE `uid` = %d AND `guid` = '%s' LIMIT 1", + intval($importer['uid']), + dbesc($guid) + ); + if(count($r)) { + logger('daspora_comment: our comment just got relayed back to us (or there was a guid collision) : ' . $guid); + return; + } + $r = q("SELECT * FROM `item` WHERE `uid` = %d AND `guid` = '%s' LIMIT 1", intval($importer['uid']), dbesc($parent_guid) @@ -517,7 +530,7 @@ function diaspora_comment($importer,$xml,$msg) { if($parent_author_signature) { - $owner_signed_data = $guid . ';' . $parent_guid . ';' . $text . ';' . $msg['author']; + $owner_signed_data = $guid . ';' . $parent_guid . ';' . $text . ';' . $diaspora_handle; $parent_author_signature = base64_decode($parent_author_signature); @@ -531,32 +544,7 @@ function diaspora_comment($importer,$xml,$msg) { // Phew! Everything checks out. Now create an item. - require_once('library/HTMLPurifier.auto.php'); - require_once('include/html2bbcode.php'); - - $body = $text; - - $maxlen = get_max_import_size(); - if($maxlen && (strlen($body) > $maxlen)) - $body = substr($body,0, $maxlen); - - if((strpos($body,'<') !== false) || (strpos($body,'>') !== false)) { - - $body = preg_replace('#]+>.+?' . 'http://www.youtube.com/((?:v|cp)/[A-Za-z0-9\-_=]+).+?#s', - '[youtube]$1[/youtube]', $body); - - $body = preg_replace('#].+?' . 'http://www.youtube.com/embed/([A-Za-z0-9\-_=]+).+?#s', - '[youtube]$1[/youtube]', $body); - - $body = oembed_html2bbcode($body); - - $config = HTMLPurifier_Config::createDefault(); - $config->set('Cache.DefinitionImpl', null); - $purifier = new HTMLPurifier($config); - $body = $purifier->purify($body); - - $body = html2bbcode($body); - } + $body = diaspora2bb($text); $message_id = $diaspora_handle . ':' . $guid; @@ -581,6 +569,7 @@ 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['app'] = 'Diaspora'; $message_id = item_store($datarray); @@ -591,13 +580,67 @@ function diaspora_comment($importer,$xml,$msg) { dbesc(base64_encode($author_signature)), dbesc($diaspora_handle) ); - } - // notify others + // 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. + + proc_run('php','include/notifier.php','comment',$message_id); + } return; +} + +function diaspora_photo($importer,$xml,$msg) { + + $remote_photo_path = notags(unxmlify($xml->remote_photo_path)); + + $remote_photo_name = notags(unxmlify($xml->remote_photo_name)); + + $status_message_guid = notags(unxmlify($xml->status_message_guid)); + + $guid = notags(unxmlify($xml->guid)); + + $diaspora_handle = notags(unxmlify($xml->diaspora_handle)); + + $public = notags(unxmlify($xml->public)); + + $created_at = notags(unxmlify($xml_created_at)); + + $contact = diaspora_get_contact_by_handle($importer['uid'],$msg['author']); + if(! $contact) + return; + + if(($contact['rel'] == CONTACT_IS_FOLLOWER) || ($contact['blocked']) || ($contact['readonly'])) { + logger('diaspora_photo: Ignoring this author.'); + http_status_exit(202); + // NOTREACHED + } + + $r = q("SELECT * FROM `item` WHERE `uid` = %d AND `guid` = '%s' LIMIT 1", + intval($importer['uid']), + dbesc($status_message_guid) + ); + if(! count($r)) { + logger('diaspora_photo: parent item not found: parent: ' . $parent_guid . ' item: ' . $guid); + return; + } + $parent_item = $r[0]; + + $link_text = '[img]' . $remote_photo_path . $remote_photo_name . '[/img]' . "\n"; + + $r = q("update item set `body` = '%s' where `id` = %d and `uid` = %d limit 1", + dbesc($link_text . $parent_item['body']), + intval($parent_item['id']), + intval($parent_item['uid']) + ); + + return; } + + + function diaspora_like($importer,$xml,$msg) { $a = get_app(); @@ -684,7 +727,8 @@ function diaspora_like($importer,$xml,$msg) { } if($parent_author_signature) { - $owner_signed_data = $guid . ';' . $parent_guid . ';' . $target_type . ';' . $positive . ';' . $msg['author']; +// $owner_signed_data = $guid . ';' . $parent_guid . ';' . $target_type . ';' . $positive . ';' . $msg['author']; + $owner_signed_data = $guid . ';' . $parent_guid . ';' . $target_type . ';' . $positive . ';' . $diaspora_handle; $parent_author_signature = base64_decode($parent_author_signature); @@ -744,6 +788,8 @@ EOT; $plink = '[url=' . $a->get_baseurl() . '/display/' . $importer['nickname'] . '/' . $parent_item['id'] . ']' . $post_type . '[/url]'; $arr['body'] = sprintf( $bodyverb, $ulink, $alink, $plink ); + $arr['app'] = 'Diaspora'; + $arr['private'] = $parent_item['private']; $arr['verb'] = $activity; $arr['object-type'] = $objtype; @@ -763,7 +809,12 @@ EOT; ); } - // FIXME send notification + // 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. + + if(! $parent_author_signature) + proc_run('php','include/notifier.php','comment',$message_id); return; } @@ -772,19 +823,32 @@ function diaspora_retraction($importer,$xml) { $guid = notags(unxmlify($xml->guid)); $diaspora_handle = notags(unxmlify($xml->diaspora_handle)); + $type = notags(unxmlify($xml->type)); $contact = diaspora_get_contact_by_handle($importer['uid'],$diaspora_handle); if(! $contact) return; -// if(($contact['rel'] == CONTACT_IS_FOLLOWER) || ($contact['blocked']) || ($contact['readonly'])) { -// logger('diaspora_retraction: Ignoring this author.'); -// http_status_exit(202); -// // NOTREACHED -// } - - + if($type === 'Person') { + contact_remove($contact['id']); + } + elseif($type === 'Post') { + $r = q("select * from item where guid = '%s' and uid = %d 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 limit 1", + dbesc(datetime_convert()), + intval($r[0]['id']) + ); + } + } + } + http_exit_status(202); + // NOTREACHED } function diaspora_share($me,$contact) { @@ -800,20 +864,55 @@ function diaspora_share($me,$contact) { $slap = 'xml=' . urlencode(urlencode(diaspora_msg_build($msg,$me,$contact,$me['prvkey'],$contact['pubkey']))); - post_url($contact['notify'] . '/',$slap); - $return_code = $a->get_curl_code(); - logger('diaspora_send_share: returns: ' . $return_code); - return $return_code; + return(diaspora_transmit($owner,$contact,$slap)); } +function diaspora_unshare($me,$contact) { + + $a = get_app(); + $myaddr = $me['nickname'] . '@' . substr($a->get_baseurl(), strpos($a->get_baseurl(),'://') + 3); + + $tpl = get_markup_template('diaspora_retract.tpl'); + $msg = replace_macros($tpl, array( + '$guid' => $me['guid'], + '$type' => 'Person', + '$handle' => $myaddr + )); + + $slap = 'xml=' . urlencode(urlencode(diaspora_msg_build($msg,$me,$contact,$me['prvkey'],$contact['pubkey']))); + + return(diaspora_transmit($owner,$contact,$slap)); + +} + + + function diaspora_send_status($item,$owner,$contact) { $a = get_app(); $myaddr = $owner['nickname'] . '@' . substr($a->get_baseurl(), strpos($a->get_baseurl(),'://') + 3); $theiraddr = $contact['addr']; - require_once('include/bbcode.php'); - $body = xmlify(bbcode($item['body'])); + $images = array(); + + $body = $item['body']; + + $cnt = preg_match_all('|\[img\](.*?)\[\/img\]|',$body,$matches,PREG_SET_ORDER); + if($cnt) { + foreach($matches as $mtch) { + $detail = array(); + $detail['str'] = $mtch[0]; + $detail['path'] = dirname($mtch[1]) . '/'; + $detail['file'] = basename($mtch[1]); + $detail['guid'] = $item['guid']; + $detail['handle'] = $myaddr; + $images[] = $detail; + $body = str_replace($detail['str'],t('link'),$body); + } + } + + $body = xmlify(html_entity_decode(bb2diaspora($body))); + $public = (($item['private']) ? 'false' : 'true'); require_once('include/datetime.php'); @@ -828,17 +927,59 @@ function diaspora_send_status($item,$owner,$contact) { '$created' => $created )); - logger('diaspora_send_status: 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']))); - post_url($contact['notify'] . '/',$slap); - $return_code = $a->get_curl_code(); - logger('diaspora_send_status: returns: ' . $return_code); + $return_code = diaspora_transmit($owner,$contact,$slap); + + if(count($images)) { + diaspora_send_images($item,$owner,$contact,$images); + } + return $return_code; } +function diaspora_send_images($item,$owner,$contact,$images) { + $a = get_app(); + if(! count($images)) + return; + $mysite = substr($a->get_baseurl(),strpos($a->get_baseurl(),'://') + 3) . '/photo'; + + $tpl = get_markup_template('diaspora_photo.tpl'); + foreach($images as $image) { + if(! stristr($image['path'],$mysite)) + continue; + $resource = str_replace('.jpg','',$image['file']); + $resource = substr($resource,0,strpos($resource,'-')); + + $r = q("select * from photo where `resource-id` = '%s' and `uid` = %d limit 1", + dbesc($resource), + intval($owner['uid']) + ); + if(! count($r)) + continue; + $public = (($r[0]['allow_cid'] || $r[0]['allow_gid'] || $r[0]['deny_cid'] || $r[0]['deny_gid']) ? 'false' : 'true' ); + $msg = replace_macros($tpl,array( + '$path' => xmlify($image['path']), + '$filename' => xmlify($image['file']), + '$msg_guid' => xmlify($image['guid']), + '$guid' => xmlify($r[0]['guid']), + '$handle' => xmlify($image['handle']), + '$public' => xmlify($public), + '$created_at' => xmlify(datetime_convert('UTC','UTC',$r[0]['created'],'Y-m-d h:i:s \U\T\C')) + )); + + + logger('diaspora_send_photo: base message: ' . $msg, LOGGER_DATA); + $slap = 'xml=' . urlencode(urlencode(diaspora_msg_build($msg,$owner,$contact,$owner['uprvkey'],$contact['pubkey']))); + + diaspora_transmit($owner,$contact,$slap); + } + +} + function diaspora_send_followup($item,$owner,$contact) { $a = get_app(); @@ -864,16 +1005,16 @@ function diaspora_send_followup($item,$owner,$contact) { $like = false; } - $text = bbcode($item['body']); + $text = html_entity_decode(bb2diaspora($item['body'])); // sign it if($like) - $signed_text = $item['guid'] . ';' . $target_type . ';' . $positive . ';' . $myaddr; + $signed_text = $item['guid'] . ';' . $target_type . ';' . $parent_guid . ';' . $positive . ';' . $myaddr; else $signed_text = $item['guid'] . ';' . $parent_guid . ';' . $text . ';' . $myaddr; - $authorsig = base64_encode(rsa_sign($signed_text,$owner['uprvkey']),'sha'); + $authorsig = base64_encode(rsa_sign($signed_text,$owner['uprvkey'],'sha')); $msg = replace_macros($tpl,array( '$guid' => xmlify($item['guid']), @@ -889,11 +1030,7 @@ function diaspora_send_followup($item,$owner,$contact) { $slap = 'xml=' . urlencode(urlencode(diaspora_msg_build($msg,$owner,$contact,$owner['uprvkey'],$contact['pubkey']))); - post_url($contact['notify'] . '/',$slap); - $return_code = $a->get_curl_code(); - logger('diaspora_send_followup: returns: ' . $return_code); - return $return_code; - + return(diaspora_transmit($owner,$contact,$slap)); } @@ -913,14 +1050,6 @@ function diaspora_send_relay($item,$owner,$contact) { else return; - // fetch the original signature - $r = q("select * from sign where iid = %d limit 1", - intval($item['id']) - ); - if(! count($r)) - return; - $orig_sign = $r[0]; - if($item['verb'] === ACTIVITY_LIKE) { $tpl = get_markup_template('diaspora_like_relay.tpl'); $like = true; @@ -932,14 +1061,57 @@ function diaspora_send_relay($item,$owner,$contact) { $like = false; } - $text = bbcode($item['body']); + $body = $item['body']; - // sign it + $itemcontact = q("select * from contact where `id` = %d limit 1", + intval($item['contact-id']) + ); + if(count($itemcontact)) { + if(! $itemcontact[0]['self']) { + $prefix = sprintf( t('[Relayed] Comment authored by %s from network %s'), + '['. $item['author-name'] . ']' . '(' . $item['author-link'] . ')', + network_to_name($itemcontact['network'])) . "\n"; + $body = $prefix . $body; + } + } - if($like) - $parent_signed_text = $orig_sign['signed_text']; - else - $parent_signed_text = $orig_sign['signed_text']; + $text = html_entity_decode(bb2diaspora($body)); + + // fetch the original signature if somebody sent the post to us to relay + // If we are relaying for a reply originating here, there wasn't a 'send to relay' + // action. It wasn't needed. In that case create the original signature and the + // owner (parent author) signature + + $r = q("select * from sign where iid = %d limit 1", + intval($item['id']) + ); + if(count($r)) { + $orig_sign = $r[0]; + $signed_text = $orig_sign['signed_text']; + $authorsig = $orig_sign['signature']; + } + else { + + + + + if($like) + $signed_text = $item['guid'] . ';' . $target_type . ';' . $parent_guid . ';' . $positive . ';' . $myaddr; + else + $signed_text = $item['guid'] . ';' . $parent_guid . ';' . $text . ';' . $myaddr; + + $authorsig = base64_encode(rsa_sign($signed_text,$owner['uprvkey'],'sha')); + + q("insert into sign (`iid`,`signed_text`,`signature`,`signer`) values (%d,'%s','%s','%s') ", + intval($item['id']), + dbesc($signed_text), + dbesc(base64_encode($authorsig)), + dbesc($myaddr) + ); + + } + + // sign it $parentauthorsig = base64_encode(rsa_sign($signed_text,$owner['uprvkey'],'sha')); @@ -949,26 +1121,16 @@ function diaspora_send_relay($item,$owner,$contact) { '$target_type' =>xmlify($target_type), '$authorsig' => xmlify($orig_sign['signature']), '$parentsig' => xmlify($parentauthorsig), - '$text' => xmlify($text), + '$body' => xmlify($text), '$positive' => xmlify($positive), - '$diaspora_handle' => xmlify($myaddr) + '$handle' => xmlify($myaddr) )); - // fetch the original signature - $r = q("select * from sign where iid = %d limit 1", - intval($item['id']) - ); - if(! count($r)) - return; - logger('diaspora_relay_comment: base message: ' . $msg, LOGGER_DATA); $slap = 'xml=' . urlencode(urlencode(diaspora_msg_build($msg,$owner,$contact,$owner['uprvkey'],$contact['pubkey']))); - post_url($contact['notify'] . '/',$slap); - $return_code = $a->get_curl_code(); - logger('diaspora_send_relay: returns: ' . $return_code); - return $return_code; + return(diaspora_transmit($owner,$contact,$slap)); } @@ -976,8 +1138,42 @@ function diaspora_send_relay($item,$owner,$contact) { function diaspora_send_retraction($item,$owner,$contact) { + $a = get_app(); + $myaddr = $owner['nickname'] . '@' . substr($a->get_baseurl(), strpos($a->get_baseurl(),'://') + 3); + + $tpl = get_markup_template('diaspora_retract.tpl'); + $msg = replace_macros($tpl, array( + '$guid' => $item['guid'], + '$type' => 'Post', + '$handle' => $myaddr + )); + + $slap = 'xml=' . urlencode(urlencode(diaspora_msg_build($msg,$owner,$contact,$owner['uprvkey'],$contact['pubkey']))); + + return(diaspora_transmit($owner,$contact,$slap)); +} +function diaspora_transmit($owner,$contact,$slap) { -} \ No newline at end of file + $a = get_app(); + + post_url($contact['notify'] . '/',$slap); + $return_code = $a->get_curl_code(); + logger('diaspora_transmit: returns: ' . $return_code); + + if(! $return_code) { + logger('diaspora_transmit: queue message'); + // queue message for redelivery + q("INSERT INTO `queue` ( `cid`, `created`, `last`, `content`) + VALUES ( %d, '%s', '%s', '%s') ", + intval($contact['id']), + dbesc(datetime_convert()), + dbesc(datetime_convert()), + dbesc($slap) + ); + } + + return(($return_code) ? $return_code : (-1)); +}