From 7ab63d210657494070b6d5c5728a998df12e1f00 Mon Sep 17 00:00:00 2001
From: Michael <heluecht@pirati.ca>
Date: Sun, 29 Nov 2020 09:01:51 +0000
Subject: [PATCH] Store the protocol of the received message

---
 mod/dfrn_notify.php           |  7 ++++---
 mod/item.php                  | 14 ++------------
 src/Model/Conversation.php    |  8 +++++---
 src/Model/Item.php            | 14 +++++++-------
 src/Protocol/DFRN.php         | 10 +++++-----
 src/Protocol/Feed.php         |  3 ++-
 src/Protocol/OStatus.php      | 11 ++++++++---
 src/Worker/Delivery.php       |  3 ++-
 static/dbstructure.config.php |  3 ++-
 9 files changed, 37 insertions(+), 36 deletions(-)

diff --git a/mod/dfrn_notify.php b/mod/dfrn_notify.php
index 8b14fe49ba..33953c6a28 100644
--- a/mod/dfrn_notify.php
+++ b/mod/dfrn_notify.php
@@ -28,6 +28,7 @@ use Friendica\Core\System;
 use Friendica\Database\DBA;
 use Friendica\DI;
 use Friendica\Model\Contact;
+use Friendica\Model\Conversation;
 use Friendica\Model\User;
 use Friendica\Protocol\DFRN;
 use Friendica\Protocol\Diaspora;
@@ -192,7 +193,7 @@ function dfrn_notify_post(App $a) {
 
 	Logger::log('Importing post from ' . $importer['addr'] . ' to ' . $importer['nickname'] . ' with the RINO ' . $rino_remote . ' encryption.', Logger::DEBUG);
 
-	$ret = DFRN::import($data, $importer);
+	$ret = DFRN::import($data, $importer, false, Conversation::PARCEL_LEGACY_DFRN);
 	System::xmlExit($ret, 'Processed');
 
 	// NOTREACHED
@@ -224,7 +225,7 @@ function dfrn_dispatch_public($postdata)
 	Logger::log('Importing post from ' . $msg['author'] . ' with the public envelope.', Logger::DEBUG);
 
 	// Now we should be able to import it
-	$ret = DFRN::import($msg['message'], $importer);
+	$ret = DFRN::import($msg['message'], $importer, false, Conversation::PARCEL_DIASPORA_DFRN);
 	System::xmlExit($ret, 'Done');
 }
 
@@ -257,7 +258,7 @@ function dfrn_dispatch_private($user, $postdata)
 	Logger::log('Importing post from ' . $msg['author'] . ' to ' . $user['nickname'] . ' with the private envelope.', Logger::DEBUG);
 
 	// Now we should be able to import it
-	$ret = DFRN::import($msg['message'], $importer);
+	$ret = DFRN::import($msg['message'], $importer, false, Conversation::PARCEL_DIASPORA_DFRN);
 	System::xmlExit($ret, 'Done');
 }
 
diff --git a/mod/item.php b/mod/item.php
index f192d9525a..6864dabacd 100644
--- a/mod/item.php
+++ b/mod/item.php
@@ -81,8 +81,6 @@ function item_post(App $a) {
 
 	$api_source = $_REQUEST['api_source'] ?? false;
 
-	$message_id = ((!empty($_REQUEST['message_id']) && $api_source) ? strip_tags($_REQUEST['message_id']) : '');
-
 	$return_path = $_REQUEST['return'] ?? '';
 	$preview = intval($_REQUEST['preview'] ?? 0);
 
@@ -176,14 +174,6 @@ function item_post(App $a) {
 		$profile_uid = $toplevel_user_id;
 	}
 
-	// Check for multiple posts with the same message id (when the post was created via API)
-	if (($message_id != '') && ($profile_uid != 0)) {
-		if (Item::exists(['uri' => $message_id, 'uid' => $profile_uid])) {
-			Logger::info('Message already exists for user', ['uri' => $message_id, 'uid' => $profile_uid]);
-			return 0;
-		}
-	}
-
 	// Allow commenting if it is an answer to a public post
 	$allow_comment = local_user() && ($profile_uid == 0) && $toplevel_item_id && in_array($toplevel_item['network'], Protocol::FEDERATED);
 
@@ -562,7 +552,7 @@ function item_post(App $a) {
 		$origin = $_REQUEST['origin'];
 	}
 
-	$uri = ($message_id ? $message_id : Item::newURI($api_source ? $profile_uid : $uid, $guid));
+	$uri = Item::newURI($api_source ? $profile_uid : $uid, $guid);
 
 	// Fallback so that we alway have a parent uri
 	if (!$thr_parent_uri || !$toplevel_item_id) {
@@ -628,7 +618,7 @@ function item_post(App $a) {
 	$datarray['api_source'] = $api_source;
 
 	// This field is for storing the raw conversation data
-	$datarray['protocol'] = Conversation::PARCEL_DFRN;
+	$datarray['protocol'] = Conversation::PARCEL_DIRECT;
 
 	$conversation = DBA::selectFirst('conversation', ['conversation-uri', 'conversation-href'], ['item-uri' => $datarray['thr-parent']]);
 	if (DBA::isResult($conversation)) {
diff --git a/src/Model/Conversation.php b/src/Model/Conversation.php
index c2f5b78bd9..d05f8af9fd 100644
--- a/src/Model/Conversation.php
+++ b/src/Model/Conversation.php
@@ -34,11 +34,15 @@ class Conversation
 	 * It currently is stored in the "protocol" field for legacy reasons.
 	 */
 	const PARCEL_ACTIVITYPUB        = 0;
-	const PARCEL_DFRN               = 1;
+	const PARCEL_DFRN               = 1; // Deprecated
 	const PARCEL_DIASPORA           = 2;
 	const PARCEL_SALMON             = 3;
 	const PARCEL_FEED               = 4; // Deprecated
 	const PARCEL_SPLIT_CONVERSATION = 6;
+	const PARCEL_LEGACY_DFRN        = 7;
+	const PARCEL_DIASPORA_DFRN      = 8;
+	const PARCEL_LOCAL_DFRN         = 9;
+	const PARCEL_DIRECT             = 10;
 	const PARCEL_TWITTER            = 67;
 	const PARCEL_UNKNOWN            = 255;
 
@@ -134,9 +138,7 @@ class Conversation
 
 		unset($arr['conversation-uri']);
 		unset($arr['conversation-href']);
-		unset($arr['protocol']);
 		unset($arr['source']);
-		unset($arr['direction']);
 
 		return $arr;
 	}
diff --git a/src/Model/Item.php b/src/Model/Item.php
index 5bc97c677f..59928fd641 100644
--- a/src/Model/Item.php
+++ b/src/Model/Item.php
@@ -1553,7 +1553,7 @@ class Item
 			$item['wall'] = 1;
 			$item['origin'] = 1;
 			$item['network'] = Protocol::DFRN;
-			$item['protocol'] = Conversation::PARCEL_DFRN;
+			$item['protocol'] = Conversation::PARCEL_DIRECT;
 
 			if (is_int($notify)) {
 				$priority = $notify;
@@ -1879,14 +1879,14 @@ class Item
 			Tag::storeFromBody($item['uri-id'], $body);
 		}
 
-		// Remove all fields that aren't part of the item table
-		foreach ($item as $field => $value) {
-			if (!in_array($field, $structure['item'])) {
-				unset($item[$field]);
+		if (Post\User::insert($item['uri-id'], $item['uid'], $item)) {
+			// Remove all fields that aren't part of the item table
+			foreach ($item as $field => $value) {
+				if (!in_array($field, $structure['item'])) {
+					unset($item[$field]);
+				}
 			}
-		}
 
-		if (Post\User::insert($item['uri-id'], $item['uid'], $item)) {
 			$condition = ['uri-id' => $item['uri-id'], 'uid' => $item['uid'], 'network' => $item['network']];
 			if (DBA::exists('item', $condition)) {
 				Logger::notice('Item is already inserted - aborting', $condition);
diff --git a/src/Protocol/DFRN.php b/src/Protocol/DFRN.php
index 22a889a851..312aae5f7b 100644
--- a/src/Protocol/DFRN.php
+++ b/src/Protocol/DFRN.php
@@ -2199,13 +2199,13 @@ class DFRN
 	 * @throws \ImagickException
 	 * @todo  Add type-hints
 	 */
-	private static function processEntry($header, $xpath, $entry, $importer, $xml)
+	private static function processEntry($header, $xpath, $entry, $importer, $xml, $protocol)
 	{
 		Logger::log("Processing entries");
 
 		$item = $header;
 
-		$item["protocol"] = Conversation::PARCEL_DFRN;
+		$item["protocol"] = $protocol;
 
 		$item["source"] = $xml;
 
@@ -2601,7 +2601,7 @@ class DFRN
 	 * @throws \ImagickException
 	 * @todo  set proper type-hints
 	 */
-	public static function import($xml, $importer, $sort_by_date = false)
+	public static function import($xml, $importer, $sort_by_date = false, $protocol = Conversation::PARCEL_DFRN)
 	{
 		if ($xml == "") {
 			return 400;
@@ -2712,7 +2712,7 @@ class DFRN
 		if (!$sort_by_date) {
 			$entries = $xpath->query("/atom:feed/atom:entry");
 			foreach ($entries as $entry) {
-				self::processEntry($header, $xpath, $entry, $importer, $xml);
+				self::processEntry($header, $xpath, $entry, $importer, $xml, $protocol);
 			}
 		} else {
 			$newentries = [];
@@ -2726,7 +2726,7 @@ class DFRN
 			ksort($newentries);
 
 			foreach ($newentries as $entry) {
-				self::processEntry($header, $xpath, $entry, $importer, $xml);
+				self::processEntry($header, $xpath, $entry, $importer, $xml, $protocol);
 			}
 		}
 		Logger::log("Import done for user " . $importer["importer_uid"] . " from contact " . $importer["id"], Logger::DEBUG);
diff --git a/src/Protocol/Feed.php b/src/Protocol/Feed.php
index 93e68241c6..dee1f204cc 100644
--- a/src/Protocol/Feed.php
+++ b/src/Protocol/Feed.php
@@ -32,6 +32,7 @@ use Friendica\Core\Protocol;
 use Friendica\Database\DBA;
 use Friendica\DI;
 use Friendica\Model\Contact;
+use Friendica\Model\Conversation;
 use Friendica\Model\Item;
 use Friendica\Model\Post;
 use Friendica\Model\Tag;
@@ -100,7 +101,7 @@ class Feed
 			$dfrn_importer = DFRN::getImporter($contact['id'], $importer['uid']);
 			if (!empty($dfrn_importer)) {
 				Logger::info('Now import the DFRN feed');
-				DFRN::import($xml, $dfrn_importer, true);
+				DFRN::import($xml, $dfrn_importer, true, Conversation::PARCEL_LEGACY_DFRN);
 				return;
 			}
 		}
diff --git a/src/Protocol/OStatus.php b/src/Protocol/OStatus.php
index 2cc815c323..a21f09544d 100644
--- a/src/Protocol/OStatus.php
+++ b/src/Protocol/OStatus.php
@@ -875,7 +875,9 @@ class OStatus
 	 */
 	private static function fetchSelf($self, array &$item)
 	{
-		$condition = ['`item-uri` = ? AND `protocol` IN (?, ?)', $self, Conversation::PARCEL_DFRN, Conversation::PARCEL_SALMON];
+		$condition = ['item-uri' => $self, 'protocol' => [Conversation::PARCEL_DFRN,
+			Conversation::PARCEL_DIASPORA_DFRN, Conversation::PARCEL_LEGACY_DFRN,
+			Conversation::PARCEL_LOCAL_DFRN, Conversation::PARCEL_DIRECT, Conversation::PARCEL_SALMON]];
 		if (DBA::exists('conversation', $condition)) {
 			Logger::log('Conversation '.$item['uri'].' is already stored.', Logger::DEBUG);
 			return;
@@ -912,8 +914,11 @@ class OStatus
 	 */
 	private static function fetchRelated($related, $related_uri, $importer)
 	{
-		$condition = ['`item-uri` = ? AND `protocol` IN (?, ?)', $related_uri, Conversation::PARCEL_DFRN, Conversation::PARCEL_SALMON];
-		$conversation = DBA::selectFirst('conversation', ['source', 'protocol'], $condition);
+		$condition = ['item-uri' => $related_uri, 'protocol' => [Conversation::PARCEL_DFRN,
+			Conversation::PARCEL_DIASPORA_DFRN, Conversation::PARCEL_LEGACY_DFRN,
+			Conversation::PARCEL_LOCAL_DFRN, Conversation::PARCEL_DIRECT, Conversation::PARCEL_SALMON]];
+	if (DBA::exists('conversation', $condition)) {
+	$conversation = DBA::selectFirst('conversation', ['source', 'protocol'], $condition);
 		if (DBA::isResult($conversation)) {
 			$stored = true;
 			$xml = $conversation['source'];
diff --git a/src/Worker/Delivery.php b/src/Worker/Delivery.php
index 8e49ee4715..fc24faef62 100644
--- a/src/Worker/Delivery.php
+++ b/src/Worker/Delivery.php
@@ -33,6 +33,7 @@ use Friendica\Protocol\Activity;
 use Friendica\Util\Strings;
 use Friendica\Util\Network;
 use Friendica\Core\Worker;
+use Friendica\Model\Conversation;
 use Friendica\Model\FContact;
 use Friendica\Protocol\Relay;
 
@@ -334,7 +335,7 @@ class Delivery
 				return;
 			}
 
-			DFRN::import($atom, $target_importer);
+			DFRN::import($atom, $target_importer, false, Conversation::PARCEL_LOCAL_DFRN);
 
 			if (in_array($cmd, [Delivery::POST, Delivery::POKE])) {
 				Model\Post\DeliveryData::incrementQueueDone($target_item['uri-id'], Model\Post\DeliveryData::DFRN);
diff --git a/static/dbstructure.config.php b/static/dbstructure.config.php
index 41c8af1de2..0574ab1849 100644
--- a/static/dbstructure.config.php
+++ b/static/dbstructure.config.php
@@ -55,7 +55,7 @@
 use Friendica\Database\DBA;
 
 if (!defined('DB_UPDATE_VERSION')) {
-	define('DB_UPDATE_VERSION', 1380);
+	define('DB_UPDATE_VERSION', 1381);
 }
 
 return [
@@ -1191,6 +1191,7 @@ return [
 		"fields" => [
 			"uri-id" => ["type" => "int unsigned", "not null" => "1", "primary" => "1", "foreign" => ["item-uri" => "id"], "comment" => "Id of the item-uri table entry that contains the item uri"],
 			"uid" => ["type" => "mediumint unsigned", "not null" => "1", "primary" => "1", "foreign" => ["user" => "uid"], "comment" => "Owner id which owns this copy of the item"],
+			"protocol" => ["type" => "tinyint unsigned", "comment" => "The used transport protocol - can be different per user"],
 			"contact-id" => ["type" => "int unsigned", "not null" => "1", "default" => "0", "foreign" => ["contact" => "id"], "comment" => "contact.id"],
 			"unseen" => ["type" => "boolean", "not null" => "1", "default" => "1", "comment" => "post has not been seen"],
 			"hidden" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => "Marker to hide the post from the user"],
-- 
2.39.5