Everything could work - needs some beautification and documentation

This commit is contained in:
Michael Vogel 2016-03-12 19:19:20 +01:00
parent 57fb0a9129
commit 0f65eee695

View file

@ -123,53 +123,43 @@ class diaspora {
$type = $fields->getName(); $type = $fields->getName();
switch ($type) { switch ($type) {
case "account_deletion": // Done case "account_deletion":
//return true;
return self::receive_account_deletion($importer, $fields); return self::receive_account_deletion($importer, $fields);
case "comment": // Done case "comment":
//return true;
return self::receive_comment($importer, $sender, $fields); return self::receive_comment($importer, $sender, $fields);
case "conversation": // Done case "conversation":
//return true;
return self::receive_conversation($importer, $msg, $fields); return self::receive_conversation($importer, $msg, $fields);
case "like": // Done case "like":
//return true;
return self::receive_like($importer, $sender, $fields); return self::receive_like($importer, $sender, $fields);
case "message": // Done case "message":
//return true;
return self::receive_message($importer, $fields); return self::receive_message($importer, $fields);
case "participation": // Not implemented case "participation": // Not implemented
return self::receive_participation($importer, $fields); return self::receive_participation($importer, $fields);
case "photo": // Not needed case "photo": // Not implemented
return self::receive_photo($importer, $fields); return self::receive_photo($importer, $fields);
case "poll_participation": // Not implemented case "poll_participation": // Not implemented
return self::receive_poll_participation($importer, $fields); return self::receive_poll_participation($importer, $fields);
case "profile": // Done case "profile":
//return true;
return self::receive_profile($importer, $fields); return self::receive_profile($importer, $fields);
case "request": case "request":
//return true;
return self::receive_request($importer, $fields); return self::receive_request($importer, $fields);
case "reshare": // Done case "reshare":
//return true;
return self::receive_reshare($importer, $fields); return self::receive_reshare($importer, $fields);
case "retraction": // Done case "retraction":
//return true;
return self::receive_retraction($importer, $sender, $fields); return self::receive_retraction($importer, $sender, $fields);
case "status_message": // Done case "status_message":
//return true;
return self::receive_status_message($importer, $fields); return self::receive_status_message($importer, $fields);
default: default:
@ -1364,7 +1354,7 @@ EOT;
$u = q("SELECT * FROM `user` WHERE `uid` = %d LIMIT 1", intval($importer["uid"])); $u = q("SELECT * FROM `user` WHERE `uid` = %d LIMIT 1", intval($importer["uid"]));
if($u) if($u)
$ret = diaspora_share($u[0], $contact_record); $ret = self::send_share($u[0], $contact_record);
} }
return true; return true;
@ -1557,8 +1547,10 @@ EOT;
case "StatusMessage": case "StatusMessage":
return self::item_retraction($importer, $contact, $data);; return self::item_retraction($importer, $contact, $data);;
case "Person": /// @todo an "unshare" shouldn't remove the contact case "Person":
contact_remove($contact["id"]); /// @todo What should we do with an "unshare"?
// Removing the contact isn't correct since we still can read the public items
//contact_remove($contact["id"]);
return true; return true;
default: default:
@ -1862,41 +1854,43 @@ EOT;
} }
} }
return(($return_code) ? $return_code : (-1)); return(($return_code) ? $return_code : (-1));
} }
public static function send_share($me,$contact) {
$myaddr = self::get_my_handle($me);
$theiraddr = $contact["addr"];
$data = array("XML" => array("post" => array("request" => array( private function build_and_transmit($owner, $contact, $type, $message, $public_batch = false, $guid = "") {
"sender_handle" => $myaddr,
"recipient_handle" => $theiraddr $data = array("XML" => array("post" => array($type => $message)));
))));
$msg = xml::from_array($data, $xml); $msg = xml::from_array($data, $xml);
$slap = self::build_message($msg, $me, $contact, $me["prvkey"], $contact["pubkey"]); logger('message: '.$msg, LOGGER_DATA);
logger('send guid '.$guid, LOGGER_DEBUG);
return(self::transmit($owner,$contact,$slap, false)); $slap = self::build_message($msg, $owner, $contact, $owner['uprvkey'], $contact['pubkey'], $public_batch);
die($slap);
$return_code = self::transmit($owner, $contact, $slap, $public_batch, false, $guid);
logger("guid: ".$item["guid"]." result ".$return_code, LOGGER_DEBUG);
return $return_code;
} }
public static function send_unshare($me,$contact) { public static function send_share($owner,$contact) {
$myaddr = self::get_my_handle($me);
$data = array("XML" => array("post" => array("retraction" => array( $message = array("sender_handle" => self::get_my_handle($owner),
"post_guid" => $me["guid"], "recipient_handle" => $contact["addr"]);
"diaspora_handle" => $myaddr,
"type" => "Person"
))));
$msg = xml::from_array($data, $xml); return self::build_and_transmit($owner, $contact, "request", $message);
}
$slap = self::build_message($msg, $me, $contact, $me["prvkey"], $contact["pubkey"]); public static function send_unshare($owner,$contact) {
return(self::transmit($owner,$contact,$slap, false)); $message = array("post_guid" => $owner["guid"],
"diaspora_handle" => self::get_my_handle($owner),
"type" => "Person");
return self::build_and_transmit($owner, $contact, "retraction", $message);
} }
private function is_reshare($body) { private function is_reshare($body) {
@ -1969,8 +1963,23 @@ EOT;
public static function send_status($item, $owner, $contact, $public_batch = false) { public static function send_status($item, $owner, $contact, $public_batch = false) {
$myaddr = self::get_my_handle($owner); $myaddr = self::get_my_handle($owner);
$theiraddr = $contact["addr"];
$public = (($item["private"]) ? "false" : "true");
$created = datetime_convert("UTC", "UTC", $item["created"], 'Y-m-d H:i:s \U\T\C');
// Detect a share element and do a reshare
if (!$item['private'] AND ($ret = self::is_reshare($item["body"]))) {
$message = array("root_diaspora_id" => $ret["root_handle"],
"root_guid" => $ret["root_guid"],
"guid" => $item["guid"],
"diaspora_handle" => $myaddr,
"public" => $public,
"created_at" => $created,
"provider_display_name" => $item["app"]);
$type = "reshare";
} else {
$title = $item["title"]; $title = $item["title"];
$body = $item["body"]; $body = $item["body"];
@ -1990,23 +1999,6 @@ EOT;
} }
} }
$public = (($item["private"]) ? "false" : "true");
$created = datetime_convert("UTC", "UTC", $item["created"], 'Y-m-d H:i:s \U\T\C');
// Detect a share element and do a reshare
if (!$item['private'] AND ($ret = self::is_reshare($item["body"]))) {
$message = array("root_diaspora_id" => $ret["root_handle"],
"root_guid" => $ret["root_guid"],
"guid" => $item["guid"],
"diaspora_handle" => $myaddr,
"public" => $public,
"created_at" => $created,
"provider_display_name" => $item["app"]);
$data = array("XML" => array("post" => array("reshare" => $message)));
} else {
$location = array(); $location = array();
if ($item["location"] != "") if ($item["location"] != "")
@ -2029,28 +2021,14 @@ EOT;
if (count($location) == 0) if (count($location) == 0)
unset($message["location"]); unset($message["location"]);
$data = array("XML" => array("post" => array("status_message" => $message))); $type = "status_message";
} }
$msg = xml::from_array($data, $xml); return self::build_and_transmit($owner, $contact, $type, $message, $public_batch, $item["guid"]);
logger("status: ".$owner["username"]." -> ".$contact["name"]." base message: ".$msg, LOGGER_DATA);
logger("send guid ".$item["guid"], LOGGER_DEBUG);
$slap = self::build_message($msg, $owner, $contact, $owner["uprvkey"], $contact["pubkey"], $public_batch);
$return_code = self::transmit($owner,$contact,$slap, false);
logger("guid: ".$item["guid"]." result ".$return_code, LOGGER_DEBUG);
return $return_code;
} }
private function construct_like($item,$owner,$contact,$public_batch = false, $data = null) { private function construct_like($item, $owner) {
if (is_array($data))
$message = $data;
else {
$myaddr = self::get_my_handle($owner); $myaddr = self::get_my_handle($owner);
$p = q("SELECT `guid`, `uri`, `parent-uri` FROM `item` WHERE `uri` = '%s' LIMIT 1", $p = q("SELECT `guid`, `uri`, `parent-uri` FROM `item` WHERE `uri` = '%s' LIMIT 1",
@ -2063,31 +2041,16 @@ EOT;
$target_type = ($parent["uri"] === $parent["parent-uri"] ? "Post" : "Comment"); $target_type = ($parent["uri"] === $parent["parent-uri"] ? "Post" : "Comment");
$positive = "true"; $positive = "true";
$message = array("positive" => $positive, return(array("positive" => $positive,
"guid" => $item["guid"], "guid" => $item["guid"],
"target_type" => $target_type, "target_type" => $target_type,
"parent_guid" => $parent["guid"], "parent_guid" => $parent["guid"],
"author_signature" => $authorsig, "author_signature" => $authorsig,
"diaspora_handle" => $myaddr); "diaspora_handle" => $myaddr));
} }
$authorsig = self::get_signature($owner, $message); private function construct_comment($item, $owner) {
if ($message["author_signature"] == "")
$message["author_signature"] = $authorsig;
else
$message["parent_author_signature"] = $authorsig;
$data = array("XML" => array("post" => array("like" => $message)));
return xml::from_array($data, $xml);
}
private function construct_comment($item,$owner,$contact,$public_batch = false, $data = null) {
if (is_array($data))
$message = $data;
else {
$myaddr = self::get_my_handle($owner); $myaddr = self::get_my_handle($owner);
$p = q("SELECT `guid` FROM `item` WHERE `parent` = %d AND `id` = %d LIMIT 1", $p = q("SELECT `guid` FROM `item` WHERE `parent` = %d AND `id` = %d LIMIT 1",
@ -2102,53 +2065,43 @@ EOT;
$text = html_entity_decode(bb2diaspora($item["body"])); $text = html_entity_decode(bb2diaspora($item["body"]));
$message = array("guid" => $item["guid"], return(array("guid" => $item["guid"],
"parent_guid" => $parent["guid"], "parent_guid" => $parent["guid"],
"author_signature" => "", "author_signature" => "",
"text" => $text, "text" => $text,
"diaspora_handle" => $myaddr); "diaspora_handle" => $myaddr));
}
$authorsig = self::get_signature($owner, $message);
if ($message["author_signature"] == "")
$message["author_signature"] = $authorsig;
else
$message["parent_author_signature"] = $authorsig;
$data = array("XML" => array("post" => array("comment" => $message)));
return xml::from_array($data, $xml);
} }
public static function send_followup($item,$owner,$contact,$public_batch = false) { public static function send_followup($item,$owner,$contact,$public_batch = false) {
if($item['verb'] === ACTIVITY_LIKE) if($item['verb'] === ACTIVITY_LIKE) {
$msg = self::construct_like($item, $owner, $contact, $public_batch); $message = self::construct_like($item, $owner);
else $type = "like";
$msg = self::construct_comment($item, $owner, $contact, $public_batch); } else {
$message = self::construct_comment($item, $owner);
$type = "comment";
}
if (!$msg) if (!$message)
return $msg; return false;
logger("base message: ".$msg, LOGGER_DATA); $message["author_signature"] = self::get_signature($owner, $message);
logger("send guid ".$item["guid"], LOGGER_DEBUG);
$slap = self::build_message($msg, $owner, $contact, $owner["uprvkey"], $contact["pubkey"], $public_batch); return self::build_and_transmit($owner, $contact, $type, $message, $public_batch, $item["guid"]);
$return_code = self::transmit($owner, $contact, $slap, $public_batch, false, $item["guid"]);
logger("guid: ".$item["guid"]." result ".$return_code, LOGGER_DEBUG);
return $return_code;
} }
function send_relay($item, $owner, $contact, $public_batch = false) { function send_relay($item, $owner, $contact, $public_batch = false) {
if ($item["deleted"]) if ($item["deleted"]) {
$sql_sign_id = "retract_iid"; $sql_sign_id = "retract_iid";
else $type = "relayable_retraction";
} elseif ($item['verb'] === ACTIVITY_LIKE) {
$sql_sign_id = "iid"; $sql_sign_id = "iid";
$type = "like";
} else {
$sql_sign_id = "iid";
$type = "comment";
}
// fetch the original signature if the relayable was created by a Diaspora // fetch the original signature if the relayable was created by a Diaspora
// or DFRN user. // or DFRN user.
@ -2157,24 +2110,32 @@ EOT;
intval($item["id"]) intval($item["id"])
); );
if(count($r)) { if (!$r)
return self::send_followup($item, $owner, $contact, $public_batch);
$orig_sign = $r[0]; $orig_sign = $r[0];
$signed_text = $orig_sign['signed_text'];
$authorsig = $orig_sign['signature']; // Old way - can be removed for the master branch
$handle = $orig_sign['signer']; if ($orig_sign['signed_text'] AND $orig_sign['signature'] AND $orig_sign['signer']) {
// Split the signed text // Split the signed text
$signed_parts = explode(";", $signed_text); $signed_parts = explode(";", $orig_sign['signed_text']);
if ($item['verb'] === ACTIVITY_LIKE) { if ($item["deleted"])
$data = array("positive" => $signed_parts[0], $message = array("parent_author_signature" => "",
"target_guid" => $signed_parts[0],
"target_type" => $signed_parts[1],
"sender_handle" => $orig_sign['signer'],
"target_author_signature" => $orig_sign['signature']);
elseif ($item['verb'] === ACTIVITY_LIKE)
$message = array("positive" => $signed_parts[0],
"guid" => $signed_parts[1], "guid" => $signed_parts[1],
"target_type" => $signed_parts[2], "target_type" => $signed_parts[2],
"parent_guid" => $signed_parts[3], "parent_guid" => $signed_parts[3],
"parent_author_signature" => "", "parent_author_signature" => "",
"author_signature" => $orig_sign['signature'], "author_signature" => $orig_sign['signature'],
"diaspora_handle" => $signed_parts[4]); "diaspora_handle" => $signed_parts[4]);
} else { else {
// Remove the comment guid // Remove the comment guid
$guid = array_shift($signed_parts); $guid = array_shift($signed_parts);
@ -2187,154 +2148,26 @@ EOT;
// Glue the parts together // Glue the parts together
$text = implode(";", $signed_parts); $text = implode(";", $signed_parts);
$data = array("guid" => $guid, $message = array("guid" => $guid,
"parent_guid" => $parent_guid, "parent_guid" => $parent_guid,
"parent_author_signature" => "", "parent_author_signature" => "",
"author_signature" => $orig_sign['signature'], "author_signature" => $orig_sign['signature'],
"text" => implode(";", $signed_parts), "text" => implode(";", $signed_parts),
"diaspora_handle" => $handle); "diaspora_handle" => $handle);
} }
} else { // New way
$message = json_decode($orig_sign['signed_text']);
} }
if ($item['deleted']) if ($item["deleted"]) {
; // Relayed Retraction $signed_text = $message["target_guid"].';'.$message["target_type"];
elseif($item['verb'] === ACTIVITY_LIKE) $message["parent_author_signature"] = base64_encode(rsa_sign($signed_text, $owner["uprvkey"], "sha256"));
$msg = self::construct_like($item, $owner, $contact, $public_batch, $data); } else
else $message["parent_author_signature"] = self::get_signature($owner, $message);
$msg = self::construct_comment($item, $owner, $contact, $public_batch, $data);
die($msg);
logger('base message: '.$msg, LOGGER_DATA); return self::build_and_transmit($owner, $contact, $type, $message, $public_batch, $item["guid"]);
logger('send guid '.$item['guid'], LOGGER_DEBUG);
$slap = self::build_message($msg,$owner, $contact, $owner['uprvkey'], $contact['pubkey'], $public_batch);
$return_code = self::transmit($owner, $contact, $slap, $public_batch, false, $item['guid']);
logger("guid: ".$item["guid"]." result ".$return_code, LOGGER_DEBUG);
return $return_code;
} }
/*
// 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'])
);
}
else {
// 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 guid, type, uri, `parent-uri` from item where parent = %d and id = %d limit 1",
intval($item['parent']),
intval($item['parent'])
);
}
if(count($p))
$parent = $p[0];
else
return;
$like = false;
$relay_retract = false;
$sql_sign_id = 'iid';
if( $item['deleted']) {
$relay_retract = true;
$target_type = ( ($item['verb'] === ACTIVITY_LIKE) ? 'Like' : 'Comment');
$sql_sign_id = 'retract_iid';
$tpl = get_markup_template('diaspora_relayable_retraction.tpl');
}
elseif($item['verb'] === ACTIVITY_LIKE) {
$like = true;
$target_type = ( $parent['uri'] === $parent['parent-uri'] ? 'Post' : 'Comment');
// $positive = (($item['deleted']) ? 'false' : 'true');
$positive = 'true';
$tpl = get_markup_template('diaspora_like_relay.tpl');
}
else { // item is a comment
$tpl = get_markup_template('diaspora_comment_relay.tpl');
}
// 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 `signed_text`, `signature`, `signer` FROM `sign` WHERE " . $sql_sign_id . " = %d LIMIT 1",
intval($item['id'])
);
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
$body = $item['body'];
$text = html_entity_decode(bb2diaspora($body));
$handle = diaspora_handle_from_contact($item['contact-id']);
if(! $handle)
return;
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;
$authorsig = base64_encode(rsa_sign($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']),
'$parent_guid' => xmlify($parent['guid']),
'$target_type' =>xmlify($target_type),
'$authorsig' => xmlify($authorsig),
'$parentsig' => xmlify($parentauthorsig),
'$body' => xmlify($text),
'$positive' => xmlify($positive),
'$handle' => xmlify($handle)
));
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,false,$item['guid']));
*/
public static function send_retraction($item, $owner, $contact, $public_batch = false) { public static function send_retraction($item, $owner, $contact, $public_batch = false) {
$myaddr = self::get_my_handle($owner); $myaddr = self::get_my_handle($owner);
@ -2355,18 +2188,7 @@ die($msg);
"sender_handle" => $myaddr, "sender_handle" => $myaddr,
"target_author_signature" => base64_encode(rsa_sign($signed_text,$owner['uprvkey'],'sha256'))); "target_author_signature" => base64_encode(rsa_sign($signed_text,$owner['uprvkey'],'sha256')));
$data = array("XML" => array("post" => array($msg_type => $message))); return self::build_and_transmit($owner, $contact, $msg_type, $message, $public_batch, $item["guid"]);
$msg = xml::from_array($data, $xml);
logger("send guid ".$item["guid"], LOGGER_DEBUG);
$slap = self::build_message($msg, $owner, $contact, $owner["uprvkey"], $contact["pubkey"], $public_batch);
$return_code = self::transmit($owner, $contact, $slap, $public_batch, false, $item["guid"]);
logger("guid: ".$item["guid"]." result ".$return_code, LOGGER_DEBUG);
return $return_code;
} }
public static function send_mail($item, $owner, $contact) { public static function send_mail($item, $owner, $contact) {
@ -2396,7 +2218,6 @@ die($msg);
$created = datetime_convert("UTC", "UTC", $item["created"], 'Y-m-d H:i:s \U\T\C'); $created = datetime_convert("UTC", "UTC", $item["created"], 'Y-m-d H:i:s \U\T\C');
$signed_text = $item["guid"].";".$cnv["guid"].";".$body.";".$created.";".$myaddr.";".$cnv['guid']; $signed_text = $item["guid"].";".$cnv["guid"].";".$body.";".$created.";".$myaddr.";".$cnv['guid'];
$sig = base64_encode(rsa_sign($signed_text, $owner["uprvkey"], "sha256")); $sig = base64_encode(rsa_sign($signed_text, $owner["uprvkey"], "sha256"));
$msg = array( $msg = array(
@ -2410,9 +2231,10 @@ die($msg);
"conversation_guid" => $cnv["guid"] "conversation_guid" => $cnv["guid"]
); );
if ($item["reply"]) if ($item["reply"]) {
$data = array("XML" => array("post" => array("message" => $msg))); $message = $msg;
else { $type = "message";
} else {
$message = array("guid" => $cnv["guid"], $message = array("guid" => $cnv["guid"],
"subject" => $cnv["subject"], "subject" => $cnv["subject"],
"created_at" => datetime_convert("UTC", "UTC", $cnv['created'], 'Y-m-d H:i:s \U\T\C'), "created_at" => datetime_convert("UTC", "UTC", $cnv['created'], 'Y-m-d H:i:s \U\T\C'),
@ -2420,21 +2242,10 @@ die($msg);
"diaspora_handle" => $cnv["creator"], "diaspora_handle" => $cnv["creator"],
"participant_handles" => $cnv["recips"]); "participant_handles" => $cnv["recips"]);
$data = array("XML" => array("post" => array("conversation" => $message))); $type = "conversation";
} }
$xmsg = xml::from_array($data, $xml); return self::build_and_transmit($owner, $contact, $type, $message, false, $item["guid"]);
logger("conversation: ".print_r($xmsg,true), LOGGER_DATA);
logger("send guid ".$item["guid"], LOGGER_DEBUG);
$slap = self::build_message($xmsg, $owner, $contact, $owner["uprvkey"], $contact["pubkey"], false);
$return_code = self::transmit($owner, $contact, $slap, false, false, $item["guid"]);
logger("guid: ".$item["guid"]." result ".$return_code, LOGGER_DEBUG);
return $return_code;
} }
} }
?> ?>