Retractions could work now.

This commit is contained in:
Michael Vogel 2016-03-03 23:34:17 +01:00
parent 5adecf5b50
commit 2edf4548dc
1 changed files with 105 additions and 65 deletions

View File

@ -13,6 +13,10 @@ require_once("include/socgraph.php");
require_once("include/group.php");
require_once("include/api.php");
/**
* @brief This class contain functions to work with XML data
*
*/
class xml {
function from_array($array, &$xml) {
@ -45,12 +49,20 @@ class xml {
}
}
}
/**
* @brief This class contain functions to create and send Diaspora XML files
*
*/
class diaspora {
/**
* @brief Dispatches public messages and find the fitting receivers
*
* @param array $msg The post that will be dispatched
*
* @return bool Was the message accepted?
*/
public static function dispatch_public($msg) {
$enabled = intval(get_config("system", "diaspora_enabled"));
@ -81,6 +93,14 @@ class diaspora {
return $item_id;
}
/**
* @brief Dispatches the different message types to the different functions
*
* @param array $importer Array of the importer user
* @param array $msg The post that will be dispatched
*
* @return bool Was the message accepted?
*/
public static function dispatch($importer, $msg) {
// The sender is the handle of the contact that sent the message.
@ -104,8 +124,8 @@ class diaspora {
//return self::import_comment($importer, $sender, $fields);
case "conversation":
return true;
//return self::import_conversation($importer, $fields);
//return true;
return self::import_conversation($importer, $fields);
case "like": // Done
return true;
@ -129,18 +149,20 @@ class diaspora {
//return self::import_profile($importer, $fields);
case "request":
//return true;
return self::import_request($importer, $fields);
case "reshare": // Done
return true;
//return self::import_reshare($importer, $fields);
case "retraction":
return self::import_retraction($importer, $fields);
case "status_message": // Done
case "retraction": // Done
return true;
//return self::import_status_message($importer, $fields);
//return self::import_retraction($importer, $sender, $fields);
case "status_message":
//return true;
return self::import_status_message($importer, $fields);
default:
logger("Unknown message type ".$type);
@ -181,6 +203,7 @@ class diaspora {
}
$type = $element->getName();
$orig_type = $type;
// All retractions are handled identically from now on.
// In the new version there will only be "retraction".
@ -235,7 +258,8 @@ class diaspora {
$signed_data .= $entry;
}
if (!in_array($fieldname, array("parent_author_signature", "target_author_signature")))
if (!in_array($fieldname, array("parent_author_signature", "target_author_signature")) OR
($orig_type == "relayable_retraction"))
xml::copy($entry, $fields, $fieldname);
}
@ -266,6 +290,13 @@ class diaspora {
return rsa_verify($signed_data, $author_signature, $key, "sha256");
}
/**
* @brief Fetches the public key for a given handle
*
* @param string $handle The handle
*
* @return string The public key
*/
private function get_key($handle) {
logger("Fetching diaspora key for: ".$handle);
@ -276,6 +307,13 @@ class diaspora {
return "";
}
/**
* @brief Fetches data for a given handle
*
* @param string $handle The handle
*
* @return array the queried data
*/
private function get_person_by_handle($handle) {
$r = q("SELECT * FROM `fcontact` WHERE `network` = '%s' AND `addr` = '%s' LIMIT 1",
@ -306,6 +344,14 @@ class diaspora {
return $person;
}
/**
* @brief Updates the fcontact table
*
* @param array $arr The fcontact data
* @param bool $update Update or insert?
*
* @return string The id of the fcontact entry
*/
private function add_fcontact($arr, $update = false) {
/// @todo Remove this function from include/network.php
@ -477,13 +523,12 @@ class diaspora {
if ($level > 5)
return false;
// This will not work if the server is not a Diaspora server
// This will work for Diaspora and newer Friendica servers
$source_url = $server."/p/".$guid.".xml";
$x = fetch_url($source_url);
if(!$x)
return false;
/// @todo - should maybe solved by the dispatcher
$source_xml = parse_xml_string($x, false);
if (!is_object($source_xml))
@ -664,7 +709,7 @@ class diaspora {
if($message_id AND $parent_item["origin"]) {
// Formerly we stored the signed text, the signature and the author in different fields.
// The new Diaspora protocol can have variable fields. We now store the data in correct order in a single field.
// We now store the raw data so that we are more flexible.
q("INSERT INTO `sign` (`iid`,`signed_text`) VALUES (%d,'%s')",
intval($message_id),
dbesc(json_encode($data))
@ -678,6 +723,7 @@ class diaspora {
}
private function import_conversation($importer, $data) {
// @todo
print_r($data);
die();
/*
@ -934,13 +980,13 @@ EOT;
$datarray["body"] = self::construct_like_body($contact, $parent_item, $guid);
$message_id = item_store($datarray);
//print_r($datarray);
// print_r($datarray);
// If we are the origin of the parent we store the original data and notify our followers
if($message_id AND $parent_item["origin"]) {
// Formerly we stored the signed text, the signature and the author in different fields.
// The new Diaspora protocol can have variable fields. We now store the data in correct order in a single field.
// We now store the raw data so that we are more flexible.
q("INSERT INTO `sign` (`iid`,`signed_text`) VALUES (%d,'%s')",
intval($message_id),
dbesc(json_encode($data))
@ -1125,7 +1171,8 @@ EOT;
}
private function import_request($importer, $data) {
print_r($data);
// @todo
print_r($data);
/*
$author = unxmlify($xml->author);
$recipient = unxmlify($xml->recipient);
@ -1371,8 +1418,8 @@ print_r($data);
if (!$contact)
return false;
// if (self::message_exists($importer["uid"], $guid))
// return false;
if (self::message_exists($importer["uid"], $guid))
return false;
$original_item = self::get_original_item($root_guid, $root_author, $author);
if (!$original_item)
@ -1414,14 +1461,22 @@ print_r($data);
$datarray["object-type"] = $original_item["object-type"];
self::fetch_guid($datarray);
//$message_id = item_store($datarray);
print_r($datarray);
$message_id = item_store($datarray);
// print_r($datarray);
return $message_id;
}
private function item_retraction($importer, $contact, $data) {
$target_type = notags(unxmlify($data->target_type));
$target_guid = notags(unxmlify($data->target_guid));
$author = notags(unxmlify($data->author));
$person = self::get_person_by_handle($author);
if (!is_array($person)) {
logger("unable to find author detail for ".$author);
return false;
}
$r = q("SELECT `id`, `parent`, `parent-uri`, `author-link` FROM `item` WHERE `guid` = '%s' AND `uid` = %d AND NOT `file` LIKE '%%[%%' LIMIT 1",
dbesc($target_guid),
@ -1431,7 +1486,15 @@ print_r($data);
return false;
// Only delete it if the author really fits
if (!link_compare($r[0]["author-link"],$contact["url"]))
if (!link_compare($r[0]["author-link"],$person["url"]))
return false;
// Check if the sender is the thread owner
$p = q("SELECT `author-link`, `origin` FROM `item` WHERE `id` = %d",
intval($r[0]["parent"]));
// Only delete it if the parent author really fits
if (!link_compare($p[0]["author-link"], $contact["url"]))
return false;
// Currently we don't have a central deletion function that we could use in this case. The function "item_drop" doesn't work for that case
@ -1443,47 +1506,36 @@ print_r($data);
delete_thread($r[0]["id"], $r[0]["parent-uri"]);
// Now check if the retraction needs to be relayed by us
//
// 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",
intval($r[0]["parent"]),
intval($r[0]["parent"])
);
if(count($p)) {
if($p[0]["origin"]) {
if($p[0]["origin"]) {
// Formerly we stored the signed text, the signature and the author in different fields.
// The new Diaspora protocol can have variable fields. We now store the data in correct order in a single field.
q("INSERT INTO `sign` (`iid`,`signed_text`) VALUES (%d,'%s')",
intval($r[0]["id"]),
dbesc(json_encode($data))
);
// Formerly we stored the signed text, the signature and the author in different fields.
// We now store the raw data so that we are more flexible.
q("INSERT INTO `sign` (`iid`,`signed_text`) VALUES (%d,'%s')",
intval($r[0]["id"]),
dbesc(json_encode($data))
);
// the existence of parent_author_signature would have meant the parent_author or owner
// is already relaying.
logger("relaying retraction");
proc_run("php", "include/notifier.php", "drop", $r[0]["id"]);
}
// notify others
proc_run("php", "include/notifier.php", "drop", $r[0]["id"]);
}
}
private function import_retraction($importer, $data) {
private function import_retraction($importer, $sender, $data) {
$target_type = notags(unxmlify($data->target_type));
$author = notags(unxmlify($data->author));
$contact = self::get_contact_by_handle($importer["uid"], $author);
$contact = self::get_contact_by_handle($importer["uid"], $sender);
if (!$contact) {
logger("cannot find contact for author: ".$author);
logger("cannot find contact for sender: ".$sender." and user ".$importer["uid"]);
return false;
}
switch ($target_type) {
case "Comment": case "Like": case "StatusMessage":
self::item_retraction($importer, $contact, $data);
break;
case "Comment":
case "Like":
case "Post": // "Post" will be supported in a future version
case "Reshare":
case "StatusMessage":
return self::item_retraction($importer, $contact, $data);;
case "Person":
contact_remove($contact["id"]);
@ -1491,6 +1543,7 @@ print_r($data);
default:
logger("Unknown target type ".$target_type);
return false;
}
return true;
}
@ -1514,8 +1567,8 @@ print_r($data);
if (!$contact)
return false;
//if (self::message_exists($importer["uid"], $guid))
// return false;
if (self::message_exists($importer["uid"], $guid))
return false;
$address = array();
if ($data->location)
@ -1539,18 +1592,6 @@ print_r($data);
$body = add_page_info_to_body($body, false, true);
}
$str_tags = "";
// This doesn't work. @todo Check if the "tag" field is filled in the "item_store" function.
$cnt = preg_match_all("/@\[url=(.*?)\[\/url\]/ism", $body, $matches, PREG_SET_ORDER);
if($cnt) {
foreach($matches as $mtch) {
if(strlen($str_tags))
$str_tags .= ",";
$str_tags .= "@[url=".$mtch[1]."[/url]";
}
}
$datarray["uid"] = $importer["uid"];
$datarray["contact-id"] = $contact["id"];
$datarray["network"] = NETWORK_DIASPORA;
@ -1573,7 +1614,6 @@ print_r($data);
$datarray["body"] = $body;
$datarray["tag"] = $str_tags;
if ($provider_display_name != "")
$datarray["app"] = $provider_display_name;
@ -1588,8 +1628,8 @@ print_r($data);
$datarray["coord"] = $address["lat"]." ".$address["lng"];
self::fetch_guid($datarray);
//$message_id = item_store($datarray);
print_r($datarray);
$message_id = item_store($datarray);
// print_r($datarray);
logger("Stored item with message id ".$message_id, LOGGER_DEBUG);