From 0b3cd206c350dad7a244e519c115fa0c03256df4 Mon Sep 17 00:00:00 2001
From: Hypolite Petovan <hypolite@mrpetovan.com>
Date: Thu, 2 Jan 2020 20:35:59 -0500
Subject: [PATCH 01/11] Remove harmful HTML decode/encode in
 BBCode::scaleExternalImages

---
 src/Content/Text/BBCode.php | 4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)

diff --git a/src/Content/Text/BBCode.php b/src/Content/Text/BBCode.php
index 11caeb6ecb..4a2a75ece3 100644
--- a/src/Content/Text/BBCode.php
+++ b/src/Content/Text/BBCode.php
@@ -444,7 +444,7 @@ class BBCode
 		}
 
 		// Picture addresses can contain special characters
-		$s = htmlspecialchars_decode($srctext);
+		$s = $srctext;
 
 		$matches = null;
 		$c = preg_match_all('/\[img.*?\](.*?)\[\/img\]/ism', $s, $matches, PREG_SET_ORDER);
@@ -501,8 +501,6 @@ class BBCode
 			}
 		}
 
-		// replace the special char encoding
-		$s = htmlspecialchars($s, ENT_NOQUOTES, 'UTF-8');
 		return $s;
 	}
 

From 542e83137b0877964467717efb994440cd7cea86 Mon Sep 17 00:00:00 2001
From: Hypolite Petovan <hypolite@mrpetovan.com>
Date: Thu, 2 Jan 2020 20:38:07 -0500
Subject: [PATCH 02/11] Remove useless HTML encode on item save

---
 mod/item.php | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/mod/item.php b/mod/item.php
index b14da4604e..52ccdb338a 100644
--- a/mod/item.php
+++ b/mod/item.php
@@ -246,7 +246,7 @@ function item_post(App $a) {
 		$app               = $orig_post['app'];
 		$categories        = $orig_post['file'];
 		$title             = Strings::escapeTags(trim($_REQUEST['title']));
-		$body              = Strings::escapeHtml(trim($body));
+		$body              = trim($body);
 		$private           = $orig_post['private'];
 		$pubmail_enabled   = $orig_post['pubmail'];
 		$network           = $orig_post['network'];
@@ -285,7 +285,7 @@ function item_post(App $a) {
 		$coord             = Strings::escapeTags(trim($_REQUEST['coord']    ?? ''));
 		$verb              = Strings::escapeTags(trim($_REQUEST['verb']     ?? ''));
 		$emailcc           = Strings::escapeTags(trim($_REQUEST['emailcc']  ?? ''));
-		$body              = Strings::escapeHtml(trim($body));
+		$body              = trim($body);
 		$network           = Strings::escapeTags(trim(($_REQUEST['network']  ?? '') ?: Protocol::DFRN));
 		$guid              = System::createUUID();
 

From 52c5b0e0f303c359c480671a84c4fc19ca190bd0 Mon Sep 17 00:00:00 2001
From: Hypolite Petovan <hypolite@mrpetovan.com>
Date: Thu, 2 Jan 2020 20:44:15 -0500
Subject: [PATCH 03/11] Remove unused BBCode::scaleExternalImage parameters

- Remove now obsolete system.no_view_full_size config key
---
 mod/item.php                  |  2 +-
 src/Content/Text/BBCode.php   | 25 ++++---------------------
 src/Content/Text/Markdown.php |  2 +-
 static/defaults.config.php    |  4 ----
 4 files changed, 6 insertions(+), 27 deletions(-)

diff --git a/mod/item.php b/mod/item.php
index 52ccdb338a..d6ce4a0944 100644
--- a/mod/item.php
+++ b/mod/item.php
@@ -509,7 +509,7 @@ function item_post(App $a) {
 	// Fold multi-line [code] sequences
 	$body = preg_replace('/\[\/code\]\s*\[code\]/ism', "\n", $body);
 
-	$body = BBCode::scaleExternalImages($body, false);
+	$body = BBCode::scaleExternalImages($body);
 
 	// Setting the object type if not defined before
 	if (!$objecttype) {
diff --git a/src/Content/Text/BBCode.php b/src/Content/Text/BBCode.php
index 4a2a75ece3..fac2b83c17 100644
--- a/src/Content/Text/BBCode.php
+++ b/src/Content/Text/BBCode.php
@@ -436,13 +436,8 @@ class BBCode
 		}
 	}
 
-	public static function scaleExternalImages($srctext, $include_link = true, $scale_replace = false)
+	public static function scaleExternalImages($srctext)
 	{
-		// Suppress "view full size"
-		if (intval(Config::get('system', 'no_view_full_size'))) {
-			$include_link = false;
-		}
-
 		// Picture addresses can contain special characters
 		$s = $srctext;
 
@@ -457,17 +452,7 @@ class BBCode
 					continue;
 				}
 
-				// $scale_replace, if passed, is an array of two elements. The
-				// first is the name of the full-size image. The second is the
-				// name of a remote, scaled-down version of the full size image.
-				// This allows Friendica to display the smaller remote image if
-				// one exists, while still linking to the full-size image
-				if ($scale_replace) {
-					$scaled = str_replace($scale_replace[0], $scale_replace[1], $mtch[1]);
-				} else {
-					$scaled = $mtch[1];
-				}
-				$i = Network::fetchUrl($scaled);
+				$i = Network::fetchUrl($mtch[1]);
 				if (!$i) {
 					return $srctext;
 				}
@@ -488,10 +473,8 @@ class BBCode
 							Logger::log('scale_external_images: ' . $orig_width . '->' . $new_width . 'w ' . $orig_height . '->' . $new_height . 'h' . ' match: ' . $mtch[0], Logger::DEBUG);
 							$s = str_replace(
 								$mtch[0],
-								'[img=' . $new_width . 'x' . $new_height. ']' . $scaled . '[/img]'
-								. "\n" . (($include_link)
-									? '[url=' . $mtch[1] . ']' . L10n::t('view full size') . '[/url]' . "\n"
-									: ''),
+								'[img=' . $new_width . 'x' . $new_height. ']' . $mtch[1] . '[/img]'
+								. "\n",
 								$s
 							);
 							Logger::log('scale_external_images: new string: ' . $s, Logger::DEBUG);
diff --git a/src/Content/Text/Markdown.php b/src/Content/Text/Markdown.php
index 8d363675fc..632282dff5 100644
--- a/src/Content/Text/Markdown.php
+++ b/src/Content/Text/Markdown.php
@@ -119,7 +119,7 @@ class Markdown
 		$s = preg_replace('/(\[code\])+(.*?)(\[\/code\])+/ism', '[code]$2[/code]', $s);
 
 		// Don't show link to full picture (until it is fixed)
-		$s = BBCode::scaleExternalImages($s, false);
+		$s = BBCode::scaleExternalImages($s);
 
 		return $s;
 	}
diff --git a/static/defaults.config.php b/static/defaults.config.php
index e8211d597d..dfec158cfe 100644
--- a/static/defaults.config.php
+++ b/static/defaults.config.php
@@ -297,10 +297,6 @@ return [
 		// Don't show smilies.
 		'no_smilies' => false,
 
-		// no_view_full_size (Boolean)
-		// Don't add the link "View full size" under a resized image.
-		'no_view_full_size' => false,
-
 		// optimize_items (Boolean)
 		// Triggers an SQL command to optimize the item table before expiring items.
 		'optimize_items' => false,

From 38fe3b8994167f8f3535e0d3eb067e43de35aba0 Mon Sep 17 00:00:00 2001
From: Hypolite Petovan <hypolite@mrpetovan.com>
Date: Fri, 3 Jan 2020 09:09:03 -0500
Subject: [PATCH 04/11] Fix formatting in  Feed::import

---
 src/Protocol/Feed.php | 49 +++++++++++++++++++++++++++++++------------
 1 file changed, 36 insertions(+), 13 deletions(-)

diff --git a/src/Protocol/Feed.php b/src/Protocol/Feed.php
index ef90c40a2a..9ca4e7b3c2 100644
--- a/src/Protocol/Feed.php
+++ b/src/Protocol/Feed.php
@@ -14,8 +14,8 @@ use Friendica\Core\Protocol;
 use Friendica\Database\DBA;
 use Friendica\DI;
 use Friendica\Model\Item;
-use Friendica\Util\ParseUrl;
 use Friendica\Util\Network;
+use Friendica\Util\ParseUrl;
 use Friendica\Util\XML;
 
 /**
@@ -35,15 +35,16 @@ class Feed {
 	 * @return array In simulation mode it returns the header and the first item
 	 * @throws \Friendica\Network\HTTPException\InternalServerErrorException
 	 */
-	public static function import($xml, $importer, &$contact, &$hub, $simulate = false) {
-
+	public static function import($xml, $importer, &$contact, &$hub, $simulate = false)
+	{
 		$a = \get_app();
 
 		if (!$simulate) {
-			Logger::log("Import Atom/RSS feed '".$contact["name"]."' (Contact ".$contact["id"].") for user ".$importer["uid"], Logger::DEBUG);
+			Logger::log("Import Atom/RSS feed '" . $contact["name"] . "' (Contact " . $contact["id"] . ") for user " . $importer["uid"], Logger::DEBUG);
 		} else {
 			Logger::log("Test Atom/RSS feed", Logger::DEBUG);
 		}
+
 		if (empty($xml)) {
 			Logger::log('XML is empty.', Logger::DEBUG);
 			return;
@@ -114,13 +115,16 @@ class Feed {
 			if (empty($author["author-name"])) {
 				$author["author-name"] = XML::getFirstNodeValue($xpath, '/atom:feed/atom:subtitle/text()');
 			}
+
 			if (empty($author["author-name"])) {
 				$author["author-name"] = XML::getFirstNodeValue($xpath, '/atom:feed/atom:author/atom:name/text()');
 			}
+
 			$value = XML::getFirstNodeValue($xpath, 'atom:author/poco:displayName/text()');
 			if ($value != "") {
 				$author["author-name"] = $value;
 			}
+
 			if ($simulate) {
 				$author["author-id"] = XML::getFirstNodeValue($xpath, '/atom:feed/atom:author/atom:id/text()');
 
@@ -134,14 +138,17 @@ class Feed {
 				if ($value != "") {
 					$author["author-nick"] = $value;
 				}
+
 				$value = XML::getFirstNodeValue($xpath, 'atom:author/poco:address/poco:formatted/text()');
 				if ($value != "") {
 					$author["author-location"] = $value;
 				}
+
 				$value = XML::getFirstNodeValue($xpath, 'atom:author/poco:note/text()');
 				if ($value != "") {
 					$author["author-about"] = $value;
 				}
+
 				$avatar = XML::getFirstAttributes($xpath, "atom:author/atom:link[@rel='avatar']");
 				if (is_object($avatar)) {
 					foreach ($avatar AS $attribute) {
@@ -169,9 +176,11 @@ class Feed {
 			if (empty($author["author-name"])) {
 				$author["author-name"] = XML::getFirstNodeValue($xpath, '/rss/channel/copyright/text()');
 			}
+
 			if (empty($author["author-name"])) {
 				$author["author-name"] = XML::getFirstNodeValue($xpath, '/rss/channel/description/text()');
 			}
+
 			$author["edited"] = $author["created"] = XML::getFirstNodeValue($xpath, '/rss/channel/pubDate/text()');
 
 			$author["app"] = XML::getFirstNodeValue($xpath, '/rss/channel/generator/text()');
@@ -185,6 +194,7 @@ class Feed {
 			if (empty($author["author-name"])) {
 				$author["author-name"] = $contact["name"];
 			}
+
 			$author["author-avatar"] = $contact["thumb"];
 
 			$author["owner-link"] = $contact["url"];
@@ -211,7 +221,7 @@ class Feed {
 
 		$items = [];
 		// Importing older entries first
-		for($i = $entries->length - 1; $i >= 0;--$i) {
+		for ($i = $entries->length - 1; $i >= 0; --$i) {
 			$entry = $entries->item($i);
 
 			$item = array_merge($header, $author);
@@ -227,9 +237,11 @@ class Feed {
 					}
 				}
 			}
+
 			if (empty($item["plink"])) {
 				$item["plink"] = XML::getFirstNodeValue($xpath, 'link/text()', $entry);
 			}
+
 			if (empty($item["plink"])) {
 				$item["plink"] = XML::getFirstNodeValue($xpath, 'rss:link/text()', $entry);
 			}
@@ -239,6 +251,7 @@ class Feed {
 			if (empty($item["uri"])) {
 				$item["uri"] = XML::getFirstNodeValue($xpath, 'guid/text()', $entry);
 			}
+
 			if (empty($item["uri"])) {
 				$item["uri"] = $item["plink"];
 			}
@@ -254,7 +267,7 @@ class Feed {
 					$importer["uid"], $item["uri"], Protocol::FEED, Protocol::DFRN];
 				$previous = Item::selectFirst(['id'], $condition);
 				if (DBA::isResult($previous)) {
-					Logger::log("Item with uri ".$item["uri"]." for user ".$importer["uid"]." already existed under id ".$previous["id"], Logger::DEBUG);
+					Logger::log("Item with uri " . $item["uri"] . " for user " . $importer["uid"] . " already existed under id " . $previous["id"], Logger::DEBUG);
 					continue;
 				}
 			}
@@ -275,9 +288,11 @@ class Feed {
 			if (empty($published)) {
 				$published = XML::getFirstNodeValue($xpath, 'pubDate/text()', $entry);
 			}
+
 			if (empty($published)) {
 				$published = XML::getFirstNodeValue($xpath, 'dc:date/text()', $entry);
 			}
+
 			$updated = XML::getFirstNodeValue($xpath, 'atom:updated/text()', $entry);
 
 			if (empty($updated) && !empty($published)) {
@@ -291,20 +306,25 @@ class Feed {
 			if ($published != "") {
 				$item["created"] = $published;
 			}
+
 			if ($updated != "") {
 				$item["edited"] = $updated;
 			}
+
 			$creator = XML::getFirstNodeValue($xpath, 'author/text()', $entry);
 
 			if (empty($creator)) {
 				$creator = XML::getFirstNodeValue($xpath, 'atom:author/atom:name/text()', $entry);
 			}
+
 			if (empty($creator)) {
 				$creator = XML::getFirstNodeValue($xpath, 'dc:creator/text()', $entry);
 			}
+
 			if ($creator != "") {
 				$item["author-name"] = $creator;
 			}
+
 			$creator = XML::getFirstNodeValue($xpath, 'dc:creator/text()', $entry);
 
 			if ($creator != "") {
@@ -332,6 +352,7 @@ class Feed {
 						$type = $attribute->textContent;
 					}
 				}
+
 				if (!empty($item["attach"])) {
 					$item["attach"] .= ',';
 				} else {
@@ -340,7 +361,7 @@ class Feed {
 
 				$attachments[] = ["link" => $href, "type" => $type, "length" => $length];
 
-				$item["attach"] .= '[attach]href="'.$href.'" length="'.$length.'" type="'.$type.'"[/attach]';
+				$item["attach"] .= '[attach]href="' . $href . '" length="' . $length . '" type="' . $type . '"[/attach]';
 			}
 
 			$tags = '';
@@ -418,7 +439,7 @@ class Feed {
 					$item["body"] = trim($item["title"]);
 				}
 
-			        $data = ParseUrl::getSiteinfoCached($item['plink'], true);
+				$data = ParseUrl::getSiteinfoCached($item['plink'], true);
 				if (!empty($data['text']) && !empty($data['title']) && (mb_strlen($item['body']) < mb_strlen($data['text']))) {
 					// When the fetched page info text is longer than the body, we do try to enhance the body
 					if (!empty($item['body']) && (strpos($data['title'], $item['body']) === false) && (strpos($data['text'], $item['body']) === false)) {
@@ -432,7 +453,7 @@ class Feed {
 
 				// We always strip the title since it will be added in the page information
 				$item["title"] = "";
-				$item["body"] = $item["body"].add_page_info($item["plink"], false, $preview, ($contact["fetch_further_information"] == 2), $contact["ffi_keyword_blacklist"]);
+				$item["body"] = $item["body"] . add_page_info($item["plink"], false, $preview, ($contact["fetch_further_information"] == 2), $contact["ffi_keyword_blacklist"]);
 				$item["tag"] = add_page_keywords($item["plink"], $preview, ($contact["fetch_further_information"] == 2), $contact["ffi_keyword_blacklist"]);
 				$item["object-type"] = Activity\ObjectType::BOOKMARK;
 				unset($item["attach"]);
@@ -448,16 +469,17 @@ class Feed {
 						// @todo $preview is never set in this case, is it intended? - @MrPetovan 2018-02-13
 						$item["tag"] = add_page_keywords($item["plink"], $preview, true, $contact["ffi_keyword_blacklist"]);
 					}
-					$item["body"] .= "\n".$item['tag'];
+					$item["body"] .= "\n" . $item['tag'];
 				}
+
 				// Add the link to the original feed entry if not present in feed
 				if (($item['plink'] != '') && !strstr($item["body"], $item['plink'])) {
-					$item["body"] .= "[hr][url]".$item['plink']."[/url]";
+					$item["body"] .= "[hr][url]" . $item['plink'] . "[/url]";
 				}
 			}
 
 			if (!$simulate) {
-				Logger::log("Stored feed: ".print_r($item, true), Logger::DEBUG);
+				Logger::log("Stored feed: " . print_r($item, true), Logger::DEBUG);
 
 				$notify = Item::isRemoteSelf($contact, $item);
 
@@ -474,10 +496,11 @@ class Feed {
 
 				$id = Item::insert($item, false, $notify);
 
-				Logger::log("Feed for contact ".$contact["url"]." stored under id ".$id);
+				Logger::log("Feed for contact " . $contact["url"] . " stored under id " . $id);
 			} else {
 				$items[] = $item;
 			}
+			
 			if ($simulate) {
 				break;
 			}

From ebaf7267440699fd5d34e7399e9d0ff754222e0a Mon Sep 17 00:00:00 2001
From: Hypolite Petovan <hypolite@mrpetovan.com>
Date: Fri, 3 Jan 2020 09:26:28 -0500
Subject: [PATCH 05/11] Rework Feed::import parameters

- Remove unused $hub
- Replace $simulate with an implicit condition
---
 include/items.php         |  2 +-
 src/Module/Debug/Feed.php |  5 +---
 src/Network/Probe.php     |  8 ++----
 src/Protocol/Feed.php     | 53 +++++++++++++++++----------------------
 4 files changed, 27 insertions(+), 41 deletions(-)

diff --git a/include/items.php b/include/items.php
index d1f0ba8787..91165344af 100644
--- a/include/items.php
+++ b/include/items.php
@@ -258,7 +258,7 @@ function consume_feed($xml, array $importer, array $contact, &$hub)
 
 	if ($contact['network'] === Protocol::FEED) {
 		Logger::log("Consume feeds", Logger::DEBUG);
-		Feed::import($xml, $importer, $contact, $hub);
+		Feed::import($xml, $importer, $contact);
 
 		return;
 	}
diff --git a/src/Module/Debug/Feed.php b/src/Module/Debug/Feed.php
index 9a48d743c8..f3e8af0c57 100644
--- a/src/Module/Debug/Feed.php
+++ b/src/Module/Debug/Feed.php
@@ -29,15 +29,12 @@ class Feed extends BaseModule
 		if (!empty($_REQUEST['url'])) {
 			$url = $_REQUEST['url'];
 
-			$importer = Model\User::getById(local_user());
-
 			$contact_id = Model\Contact::getIdForURL($url, local_user(), true);
 			$contact = Model\Contact::getById($contact_id);
 
 			$xml = Network::fetchUrl($contact['poll']);
 
-			$dummy = null;
-			$import_result = Protocol\Feed::import($xml, $importer, $contact, $dummy, true);
+			$import_result = Protocol\Feed::import($xml);
 
 			$result = [
 				'input' => $xml,
diff --git a/src/Network/Probe.php b/src/Network/Probe.php
index dac0822a94..122df70ce7 100644
--- a/src/Network/Probe.php
+++ b/src/Network/Probe.php
@@ -1480,10 +1480,7 @@ class Probe
 			return false;
 		}
 		$feed = $curlResult->getBody();
-		$dummy1 = null;
-		$dummy2 = null;
-		$dummy2 = null;
-		$feed_data = Feed::import($feed, $dummy1, $dummy2, $dummy3, true);
+		$feed_data = Feed::import($feed);
 		if (!$feed_data) {
 			return false;
 		}
@@ -1763,8 +1760,7 @@ class Probe
 			return false;
 		}
 		$feed = $curlResult->getBody();
-		$dummy1 = $dummy2 = $dummy3 = null;
-		$feed_data = Feed::import($feed, $dummy1, $dummy2, $dummy3, true);
+		$feed_data = Feed::import($feed);
 
 		if (!$feed_data) {
 			if (!$probe) {
diff --git a/src/Protocol/Feed.php b/src/Protocol/Feed.php
index 9ca4e7b3c2..751a0f1e90 100644
--- a/src/Protocol/Feed.php
+++ b/src/Protocol/Feed.php
@@ -29,25 +29,23 @@ class Feed {
 	 * @param string $xml      The feed data
 	 * @param array  $importer The user record of the importer
 	 * @param array  $contact  The contact record of the feed
-	 * @param string $hub      Unused dummy value for compatibility reasons
-	 * @param bool   $simulate If enabled, no data is imported
 	 *
-	 * @return array In simulation mode it returns the header and the first item
+	 * @return array Returns the header and the first item in dry run mode
 	 * @throws \Friendica\Network\HTTPException\InternalServerErrorException
 	 */
-	public static function import($xml, $importer, &$contact, &$hub, $simulate = false)
+	public static function import($xml, array $importer = [], array $contact = [])
 	{
-		$a = \get_app();
+		$dryRun = empty($importer) && empty($contact);
 
-		if (!$simulate) {
-			Logger::log("Import Atom/RSS feed '" . $contact["name"] . "' (Contact " . $contact["id"] . ") for user " . $importer["uid"], Logger::DEBUG);
+		if ($dryRun) {
+			Logger::info("Test Atom/RSS feed");
 		} else {
-			Logger::log("Test Atom/RSS feed", Logger::DEBUG);
+			Logger::info("Import Atom/RSS feed '" . $contact["name"] . "' (Contact " . $contact["id"] . ") for user " . $importer["uid"]);
 		}
 
 		if (empty($xml)) {
-			Logger::log('XML is empty.', Logger::DEBUG);
-			return;
+			Logger::info('XML is empty.');
+			return [];
 		}
 
 		if (!empty($contact['poll'])) {
@@ -125,7 +123,7 @@ class Feed {
 				$author["author-name"] = $value;
 			}
 
-			if ($simulate) {
+			if ($dryRun) {
 				$author["author-id"] = XML::getFirstNodeValue($xpath, '/atom:feed/atom:author/atom:id/text()');
 
 				// See https://tools.ietf.org/html/rfc4287#section-3.2.2
@@ -188,7 +186,7 @@ class Feed {
 			$entries = $xpath->query('/rss/channel/item');
 		}
 
-		if (!$simulate) {
+		if (!$dryRun) {
 			$author["author-link"] = $contact["url"];
 
 			if (empty($author["author-name"])) {
@@ -203,7 +201,7 @@ class Feed {
 		}
 
 		$header = [];
-		$header["uid"] = $importer["uid"];
+		$header["uid"] = $importer["uid"] ?? 0;
 		$header["network"] = Protocol::FEED;
 		$header["wall"] = 0;
 		$header["origin"] = 0;
@@ -212,11 +210,11 @@ class Feed {
 		$header["verb"] = Activity::POST;
 		$header["object-type"] = Activity\ObjectType::NOTE;
 
-		$header["contact-id"] = $contact["id"];
+		$header["contact-id"] = $contact["id"] ?? 0;
 
 		if (!is_object($entries)) {
-			Logger::log("There are no entries in this feed.", Logger::DEBUG);
-			return;
+			Logger::info("There are no entries in this feed.");
+			return [];
 		}
 
 		$items = [];
@@ -262,12 +260,12 @@ class Feed {
 
 			$item["parent-uri"] = $item["uri"];
 
-			if (!$simulate) {
+			if (!$dryRun) {
 				$condition = ["`uid` = ? AND `uri` = ? AND `network` IN (?, ?)",
 					$importer["uid"], $item["uri"], Protocol::FEED, Protocol::DFRN];
 				$previous = Item::selectFirst(['id'], $condition);
 				if (DBA::isResult($previous)) {
-					Logger::log("Item with uri " . $item["uri"] . " for user " . $importer["uid"] . " already existed under id " . $previous["id"], Logger::DEBUG);
+					Logger::info("Item with uri " . $item["uri"] . " for user " . $importer["uid"] . " already existed under id " . $previous["id"]);
 					continue;
 				}
 			}
@@ -478,8 +476,11 @@ class Feed {
 				}
 			}
 
-			if (!$simulate) {
-				Logger::log("Stored feed: " . print_r($item, true), Logger::DEBUG);
+			if ($dryRun) {
+				$items[] = $item;
+				break;
+			} else {
+				Logger::info("Stored feed: " . print_r($item, true));
 
 				$notify = Item::isRemoteSelf($contact, $item);
 
@@ -496,19 +497,11 @@ class Feed {
 
 				$id = Item::insert($item, false, $notify);
 
-				Logger::log("Feed for contact " . $contact["url"] . " stored under id " . $id);
-			} else {
-				$items[] = $item;
-			}
-			
-			if ($simulate) {
-				break;
+				Logger::info("Feed for contact " . $contact["url"] . " stored under id " . $id);
 			}
 		}
 
-		if ($simulate) {
-			return ["header" => $author, "items" => $items];
-		}
+		return ["header" => $author, "items" => $items];
 	}
 
 	private static function titleIsBody($title, $body)

From 4461c16165fd58d08d2aa430c7d7dd955bb0e7b2 Mon Sep 17 00:00:00 2001
From: Hypolite Petovan <hypolite@mrpetovan.com>
Date: Fri, 3 Jan 2020 09:30:35 -0500
Subject: [PATCH 06/11] Remove superfluous comment in
 BBCode::scaleExternalImage

---
 src/Content/Text/BBCode.php | 1 -
 1 file changed, 1 deletion(-)

diff --git a/src/Content/Text/BBCode.php b/src/Content/Text/BBCode.php
index fac2b83c17..51fa08ad3d 100644
--- a/src/Content/Text/BBCode.php
+++ b/src/Content/Text/BBCode.php
@@ -438,7 +438,6 @@ class BBCode
 
 	public static function scaleExternalImages($srctext)
 	{
-		// Picture addresses can contain special characters
 		$s = $srctext;
 
 		$matches = null;

From 7cf27e9cb035e151edc2826795499c13edb832c8 Mon Sep 17 00:00:00 2001
From: Michael <heluecht@pirati.ca>
Date: Sat, 4 Jan 2020 14:35:14 +0000
Subject: [PATCH 07/11] AP: Transmit the language in the contentMap

---
 src/Protocol/ActivityPub/Transmitter.php | 44 +++++++++++++++++++++---
 1 file changed, 39 insertions(+), 5 deletions(-)

diff --git a/src/Protocol/ActivityPub/Transmitter.php b/src/Protocol/ActivityPub/Transmitter.php
index d5dfc14fc0..7feb70ba78 100644
--- a/src/Protocol/ActivityPub/Transmitter.php
+++ b/src/Protocol/ActivityPub/Transmitter.php
@@ -1304,12 +1304,17 @@ class Transmitter
 			$data['content'] = BBCode::convert($body, false, 9);
 		}
 
-		$regexp = "/[@!]\[url\=([^\[\]]*)\].*?\[\/url\]/ism";
-		$richbody = preg_replace_callback($regexp, ['self', 'mentionCallback'], $item['body']);
-		$richbody = BBCode::removeAttachment($richbody);
+		// The regular "content" field does contain a minimized HTML. This is done since systems like
+		// Mastodon has got problems with - for example - embedded pictures.
+		// The contentMap does contain the unmodified HTML.
+		$language = self::getLanguage($item);
+		if (!empty($language)) {
+			$regexp = "/[@!]\[url\=([^\[\]]*)\].*?\[\/url\]/ism";
+			$richbody = preg_replace_callback($regexp, ['self', 'mentionCallback'], $item['body']);
+			$richbody = BBCode::removeAttachment($richbody);
 
-		$data['contentMap']['text/html'] = BBCode::convert($richbody, false);
-		$data['contentMap']['text/markdown'] = BBCode::toMarkdown($item["body"]);
+			$data['contentMap'][$language] = BBCode::convert($richbody, false);
+		}
 
 		$data['source'] = ['content' => $item['body'], 'mediaType' => "text/bbcode"];
 
@@ -1333,6 +1338,35 @@ class Transmitter
 		return $data;
 	}
 
+	/**
+	 * Fetches the language from the post, the user or the system.
+	 *
+	 * @param array $item
+	 *
+	 * @return string language string
+	 */
+	private static function getLanguage($item)
+	{
+		// Try to fetch the language from the post itself
+		if (!empty($item['language'])) {
+			$languages = array_keys(json_decode($item['language'], true));
+			if (!empty($languages[0])) {
+				return $languages[0];
+			}
+		}
+
+		// Otherwise use the user's language
+		if (!empty($item['uid'])) {
+			$user = DBA::selectFirst('user', ['language'], ['uid' => $item['uid']]);
+			if (!empty($user['language'])) {
+				return $user['language'];
+			}
+		}
+
+		// And finally just use the system language
+		return Config::get('system', 'language');
+	}
+
 	/**
 	 * Creates an an "add tag" entry
 	 *

From b08c9692ca6bd12484b0993f701d8a62c854f274 Mon Sep 17 00:00:00 2001
From: Michael <heluecht@pirati.ca>
Date: Sat, 4 Jan 2020 21:48:26 +0000
Subject: [PATCH 08/11] Added parameter type

---
 src/Protocol/ActivityPub/Transmitter.php | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/Protocol/ActivityPub/Transmitter.php b/src/Protocol/ActivityPub/Transmitter.php
index 7feb70ba78..6a512323cf 100644
--- a/src/Protocol/ActivityPub/Transmitter.php
+++ b/src/Protocol/ActivityPub/Transmitter.php
@@ -1345,7 +1345,7 @@ class Transmitter
 	 *
 	 * @return string language string
 	 */
-	private static function getLanguage($item)
+	private static function getLanguage(array $item)
 	{
 		// Try to fetch the language from the post itself
 		if (!empty($item['language'])) {

From 07b4ceecd2cd8a7087366aa48744924f593bc622 Mon Sep 17 00:00:00 2001
From: nupplaPhil <admin@philipp.info>
Date: Sun, 5 Jan 2020 00:10:34 +0100
Subject: [PATCH 09/11] Remove deprecated rdirname() in favor of native
 dirname()

---
 boot.php            | 19 -------------------
 src/App/BaseURL.php |  2 +-
 2 files changed, 1 insertion(+), 20 deletions(-)

diff --git a/boot.php b/boot.php
index fa99a7bb39..8ce33b2bdf 100644
--- a/boot.php
+++ b/boot.php
@@ -683,22 +683,3 @@ function validate_include(&$file)
 	// Simply return flag
 	return $valid;
 }
-
-/**
- * PHP 5 compatible dirname() with count parameter
- *
- * @see http://php.net/manual/en/function.dirname.php#113193
- *
- * @deprecated with PHP 7
- * @param string $path
- * @param int    $levels
- * @return string
- */
-function rdirname($path, $levels = 1)
-{
-	if ($levels > 1) {
-		return dirname(rdirname($path, --$levels));
-	} else {
-		return dirname($path);
-	}
-}
diff --git a/src/App/BaseURL.php b/src/App/BaseURL.php
index 6b79fad466..7c286514a6 100644
--- a/src/App/BaseURL.php
+++ b/src/App/BaseURL.php
@@ -355,7 +355,7 @@ class BaseURL
 		if (!empty($relative_script_path)) {
 			// Module
 			if (!empty($this->server['QUERY_STRING'])) {
-				$this->urlPath = trim(rdirname($relative_script_path, substr_count(trim($this->server['QUERY_STRING'], '/'), '/') + 1), '/');
+				$this->urlPath = trim(dirname($relative_script_path, substr_count(trim($this->server['QUERY_STRING'], '/'), '/') + 1), '/');
 			} else {
 				// Root page
 				$this->urlPath = trim($relative_script_path, '/');

From f0eea6f87590f10081f5bc61395bb7eca9e76ec5 Mon Sep 17 00:00:00 2001
From: nupplaPhil <admin@philipp.info>
Date: Sat, 4 Jan 2020 23:42:01 +0100
Subject: [PATCH 10/11] Remove get_app() in favor of DI::app()

---
 boot.php                              | 20 +------
 include/api.php                       | 86 +++++++++++++--------------
 include/enotify.php                   |  2 +-
 mod/fbrowser.php                      |  2 +-
 mod/item.php                          |  2 +-
 mod/message.php                       |  2 +-
 mod/settings.php                      |  2 +-
 src/BaseModule.php                    |  8 +--
 src/Console/DocBloxErrorChecker.php   | 14 ++++-
 src/Console/PhpToPo.php               | 14 ++++-
 src/Content/OEmbed.php                |  2 +-
 src/Content/Text/HTML.php             |  3 +-
 src/Content/Widget.php                |  4 +-
 src/Content/Widget/CalendarExport.php |  3 +-
 src/Core/Worker.php                   |  6 +-
 src/Model/Contact.php                 |  2 +-
 src/Model/Mail.php                    |  2 +-
 src/Model/Photo.php                   |  2 +-
 src/Model/Profile.php                 |  8 +--
 src/Protocol/DFRN.php                 |  2 +-
 src/Render/FriendicaSmarty.php        |  3 +-
 src/Render/FriendicaSmartyEngine.php  |  5 +-
 src/Util/Network.php                  |  6 +-
 tests/include/ApiTest.php             |  2 +-
 view/theme/frio/php/scheme.php        |  3 +-
 view/theme/vier/theme.php             |  2 +-
 26 files changed, 110 insertions(+), 97 deletions(-)

diff --git a/boot.php b/boot.php
index fa99a7bb39..d54ee72a3d 100644
--- a/boot.php
+++ b/boot.php
@@ -234,20 +234,6 @@ if (!defined('CURLE_OPERATION_TIMEDOUT')) {
 	define('CURLE_OPERATION_TIMEDOUT', CURLE_OPERATION_TIMEOUTED);
 }
 
-/**
- * @brief Retrieve the App structure
- *
- * Useful in functions which require it but don't get it passed to them
- *
- * @deprecated since version 2018.09
- * @see DI::app()
- * @return App
- */
-function get_app()
-{
-	return DI::app();
-}
-
 /**
  * @brief Used to end the current process, after saving session state.
  * @deprecated
@@ -325,7 +311,7 @@ function notice($s)
 		return;
 	}
 
-	$a = \get_app();
+	$a = DI::app();
 	if (empty($_SESSION['sysmsg'])) {
 		$_SESSION['sysmsg'] = [];
 	}
@@ -343,7 +329,7 @@ function notice($s)
  */
 function info($s)
 {
-	$a = \get_app();
+	$a = DI::app();
 
 	if (local_user() && PConfig::get(local_user(), 'system', 'ignore_info')) {
 		return;
@@ -406,7 +392,7 @@ function feed_birthday($uid, $tz)
  */
 function is_site_admin()
 {
-	$a = \get_app();
+	$a = DI::app();
 
 	$admin_email = Config::get('config', 'admin_email');
 
diff --git a/include/api.php b/include/api.php
index a6a6b50500..ac0ba26c12 100644
--- a/include/api.php
+++ b/include/api.php
@@ -930,7 +930,7 @@ function api_format_data($root_element, $type, $data)
  */
 function api_account_verify_credentials($type)
 {
-	$a = \get_app();
+	$a = DI::app();
 
 	if (api_user() === false) {
 		throw new ForbiddenException();
@@ -998,7 +998,7 @@ function requestdata($k)
  */
 function api_statuses_mediap($type)
 {
-	$a = \get_app();
+	$a = DI::app();
 
 	if (api_user() === false) {
 		Logger::log('api_statuses_update: no user');
@@ -1052,7 +1052,7 @@ api_register_func('api/statuses/mediap', 'api_statuses_mediap', true, API_METHOD
  */
 function api_statuses_update($type)
 {
-	$a = \get_app();
+	$a = DI::app();
 
 	if (api_user() === false) {
 		Logger::log('api_statuses_update: no user');
@@ -1202,7 +1202,7 @@ api_register_func('api/statuses/update_with_media', 'api_statuses_update', true,
  */
 function api_media_upload()
 {
-	$a = \get_app();
+	$a = DI::app();
 
 	if (api_user() === false) {
 		Logger::log('no user');
@@ -1257,7 +1257,7 @@ api_register_func('api/media/upload', 'api_media_upload', true, API_METHOD_POST)
  */
 function api_media_metadata_create($type)
 {
-	$a = \get_app();
+	$a = DI::app();
 
 	if (api_user() === false) {
 		Logger::info('no user');
@@ -1404,7 +1404,7 @@ api_register_func('api/externalprofile/show', 'api_users_show');
  */
 function api_users_search($type)
 {
-	$a = \get_app();
+	$a = DI::app();
 
 	$userlist = [];
 
@@ -1466,7 +1466,7 @@ function api_users_lookup($type)
 	if (!empty($_REQUEST['user_id'])) {
 		foreach (explode(',', $_REQUEST['user_id']) as $id) {
 			if (!empty($id)) {
-				$users[] = api_get_user(get_app(), $id);
+				$users[] = api_get_user(DI::app(), $id);
 			}
 		}
 	}
@@ -1497,7 +1497,7 @@ api_register_func('api/users/lookup', 'api_users_lookup', true);
  */
 function api_search($type)
 {
-	$a = \get_app();
+	$a = DI::app();
 	$user_info = api_get_user($a);
 
 	if (api_user() === false || $user_info === false) {
@@ -1611,7 +1611,7 @@ api_register_func('api/search', 'api_search', true);
  */
 function api_statuses_home_timeline($type)
 {
-	$a = \get_app();
+	$a = DI::app();
 	$user_info = api_get_user($a);
 
 	if (api_user() === false || $user_info === false) {
@@ -1704,7 +1704,7 @@ api_register_func('api/statuses/friends_timeline', 'api_statuses_home_timeline',
  */
 function api_statuses_public_timeline($type)
 {
-	$a = \get_app();
+	$a = DI::app();
 	$user_info = api_get_user($a);
 
 	if (api_user() === false || $user_info === false) {
@@ -1789,7 +1789,7 @@ api_register_func('api/statuses/public_timeline', 'api_statuses_public_timeline'
  */
 function api_statuses_networkpublic_timeline($type)
 {
-	$a = \get_app();
+	$a = DI::app();
 	$user_info = api_get_user($a);
 
 	if (api_user() === false || $user_info === false) {
@@ -1850,7 +1850,7 @@ api_register_func('api/statuses/networkpublic_timeline', 'api_statuses_networkpu
  */
 function api_statuses_show($type)
 {
-	$a = \get_app();
+	$a = DI::app();
 	$user_info = api_get_user($a);
 
 	if (api_user() === false || $user_info === false) {
@@ -1929,7 +1929,7 @@ api_register_func('api/statuses/show', 'api_statuses_show', true);
  */
 function api_conversation_show($type)
 {
-	$a = \get_app();
+	$a = DI::app();
 	$user_info = api_get_user($a);
 
 	if (api_user() === false || $user_info === false) {
@@ -2011,7 +2011,7 @@ function api_statuses_repeat($type)
 {
 	global $called_api;
 
-	$a = \get_app();
+	$a = DI::app();
 
 	if (api_user() === false) {
 		throw new ForbiddenException();
@@ -2088,7 +2088,7 @@ api_register_func('api/statuses/retweet', 'api_statuses_repeat', true, API_METHO
  */
 function api_statuses_destroy($type)
 {
-	$a = \get_app();
+	$a = DI::app();
 
 	if (api_user() === false) {
 		throw new ForbiddenException();
@@ -2135,7 +2135,7 @@ api_register_func('api/statuses/destroy', 'api_statuses_destroy', true, API_METH
  */
 function api_statuses_mentions($type)
 {
-	$a = \get_app();
+	$a = DI::app();
 	$user_info = api_get_user($a);
 
 	if (api_user() === false || $user_info === false) {
@@ -2204,7 +2204,7 @@ api_register_func('api/statuses/replies', 'api_statuses_mentions', true);
  */
 function api_statuses_user_timeline($type)
 {
-	$a = \get_app();
+	$a = DI::app();
 	$user_info = api_get_user($a);
 
 	if (api_user() === false || $user_info === false) {
@@ -2288,7 +2288,7 @@ api_register_func('api/statuses/user_timeline', 'api_statuses_user_timeline', tr
  */
 function api_favorites_create_destroy($type)
 {
-	$a = \get_app();
+	$a = DI::app();
 
 	if (api_user() === false) {
 		throw new ForbiddenException();
@@ -2371,7 +2371,7 @@ function api_favorites($type)
 {
 	global $called_api;
 
-	$a = \get_app();
+	$a = DI::app();
 	$user_info = api_get_user($a);
 
 	if (api_user() === false || $user_info === false) {
@@ -2836,7 +2836,7 @@ function api_contactlink_to_array($txt)
  */
 function api_format_items_activities($item, $type = "json")
 {
-	$a = \get_app();
+	$a = DI::app();
 
 	$activities = [
 		'like' => [],
@@ -3257,7 +3257,7 @@ api_register_func('api/lists/subscriptions', 'api_lists_list', true);
  */
 function api_lists_ownerships($type)
 {
-	$a = \get_app();
+	$a = DI::app();
 
 	if (api_user() === false) {
 		throw new ForbiddenException();
@@ -3306,7 +3306,7 @@ api_register_func('api/lists/ownerships', 'api_lists_ownerships', true);
  */
 function api_lists_statuses($type)
 {
-	$a = \get_app();
+	$a = DI::app();
 
 	$user_info = api_get_user($a);
 	if (api_user() === false || $user_info === false) {
@@ -3384,7 +3384,7 @@ api_register_func('api/lists/statuses', 'api_lists_statuses', true);
  */
 function api_statuses_f($qtype)
 {
-	$a = \get_app();
+	$a = DI::app();
 
 	if (api_user() === false) {
 		throw new ForbiddenException();
@@ -3636,7 +3636,7 @@ function api_ff_ids($type, int $rel)
 		throw new ForbiddenException();
 	}
 
-	$a = \get_app();
+	$a = DI::app();
 
 	api_get_user($a);
 
@@ -3723,7 +3723,7 @@ api_register_func('api/followers/ids', 'api_followers_ids', true);
  */
 function api_direct_messages_new($type)
 {
-	$a = \get_app();
+	$a = DI::app();
 
 	if (api_user() === false) {
 		throw new ForbiddenException();
@@ -3815,7 +3815,7 @@ api_register_func('api/direct_messages/new', 'api_direct_messages_new', true, AP
  */
 function api_direct_messages_destroy($type)
 {
-	$a = \get_app();
+	$a = DI::app();
 
 	if (api_user() === false) {
 		throw new ForbiddenException();
@@ -3983,7 +3983,7 @@ api_register_func('api/friendships/destroy', 'api_friendships_destroy', true, AP
  */
 function api_direct_messages_box($type, $box, $verbose)
 {
-	$a = \get_app();
+	$a = DI::app();
 	if (api_user() === false) {
 		throw new ForbiddenException();
 	}
@@ -4627,7 +4627,7 @@ function api_account_update_profile_image($type)
 	Contact::updateSelfFromUserID(api_user(), true);
 
 	// Update global directory in background
-	$url = DI::baseUrl() . '/profile/' . \get_app()->user['nickname'];
+	$url = DI::baseUrl() . '/profile/' . DI::app()->user['nickname'];
 	if ($url && strlen(Config::get('system', 'directory'))) {
 		Worker::add(PRIORITY_LOW, "Directory", $url);
 	}
@@ -4668,7 +4668,7 @@ api_register_func('api/account/update_profile_image', 'api_account_update_profil
 function api_account_update_profile($type)
 {
 	$local_user = api_user();
-	$api_user = api_get_user(get_app());
+	$api_user = api_get_user(DI::app());
 
 	if (!empty($_POST['name'])) {
 		DBA::update('profile', ['name' => $_POST['name']], ['uid' => $local_user]);
@@ -4963,7 +4963,7 @@ function post_photo_item($hash, $allow_cid, $deny_cid, $allow_gid, $deny_gid, $f
  */
 function prepare_photo_data($type, $scale, $photo_id)
 {
-	$a = \get_app();
+	$a = DI::app();
 	$user_info = api_get_user($a);
 
 	if ($user_info === false) {
@@ -5391,7 +5391,7 @@ function api_best_nickname(&$contacts)
  */
 function api_friendica_group_show($type)
 {
-	$a = \get_app();
+	$a = DI::app();
 
 	if (api_user() === false) {
 		throw new ForbiddenException();
@@ -5461,7 +5461,7 @@ api_register_func('api/friendica/group_show', 'api_friendica_group_show', true);
  */
 function api_friendica_group_delete($type)
 {
-	$a = \get_app();
+	$a = DI::app();
 
 	if (api_user() === false) {
 		throw new ForbiddenException();
@@ -5528,7 +5528,7 @@ api_register_func('api/friendica/group_delete', 'api_friendica_group_delete', tr
  */
 function api_lists_destroy($type)
 {
-	$a = \get_app();
+	$a = DI::app();
 
 	if (api_user() === false) {
 		throw new ForbiddenException();
@@ -5650,7 +5650,7 @@ function group_create($name, $uid, $users = [])
  */
 function api_friendica_group_create($type)
 {
-	$a = \get_app();
+	$a = DI::app();
 
 	if (api_user() === false) {
 		throw new ForbiddenException();
@@ -5684,7 +5684,7 @@ api_register_func('api/friendica/group_create', 'api_friendica_group_create', tr
  */
 function api_lists_create($type)
 {
-	$a = \get_app();
+	$a = DI::app();
 
 	if (api_user() === false) {
 		throw new ForbiddenException();
@@ -5723,7 +5723,7 @@ api_register_func('api/lists/create', 'api_lists_create', true, API_METHOD_POST)
  */
 function api_friendica_group_update($type)
 {
-	$a = \get_app();
+	$a = DI::app();
 
 	if (api_user() === false) {
 		throw new ForbiddenException();
@@ -5802,7 +5802,7 @@ api_register_func('api/friendica/group_update', 'api_friendica_group_update', tr
  */
 function api_lists_update($type)
 {
-	$a = \get_app();
+	$a = DI::app();
 
 	if (api_user() === false) {
 		throw new ForbiddenException();
@@ -5852,7 +5852,7 @@ api_register_func('api/lists/update', 'api_lists_update', true, API_METHOD_POST)
  */
 function api_friendica_activity($type)
 {
-	$a = \get_app();
+	$a = DI::app();
 
 	if (api_user() === false) {
 		throw new ForbiddenException();
@@ -5899,7 +5899,7 @@ api_register_func('api/friendica/activity/unattendmaybe', 'api_friendica_activit
  */
 function api_friendica_notification($type)
 {
-	$a = \get_app();
+	$a = DI::app();
 
 	if (api_user() === false) {
 		throw new ForbiddenException();
@@ -5937,7 +5937,7 @@ function api_friendica_notification($type)
  */
 function api_friendica_notification_seen($type)
 {
-	$a = \get_app();
+	$a = DI::app();
 	$user_info = api_get_user($a);
 
 	if (api_user() === false || $user_info === false) {
@@ -5987,7 +5987,7 @@ api_register_func('api/friendica/notification', 'api_friendica_notification', tr
  */
 function api_friendica_direct_messages_setseen($type)
 {
-	$a = \get_app();
+	$a = DI::app();
 	if (api_user() === false) {
 		throw new ForbiddenException();
 	}
@@ -6041,7 +6041,7 @@ api_register_func('api/friendica/direct_messages_setseen', 'api_friendica_direct
  */
 function api_friendica_direct_messages_search($type, $box = "")
 {
-	$a = \get_app();
+	$a = DI::app();
 
 	if (api_user() === false) {
 		throw new ForbiddenException();
@@ -6109,7 +6109,7 @@ api_register_func('api/friendica/direct_messages_search', 'api_friendica_direct_
  */
 function api_friendica_profile_show($type)
 {
-	$a = \get_app();
+	$a = DI::app();
 
 	if (api_user() === false) {
 		throw new ForbiddenException();
diff --git a/include/enotify.php b/include/enotify.php
index 1ddc9372ab..0c78e569b9 100644
--- a/include/enotify.php
+++ b/include/enotify.php
@@ -33,7 +33,7 @@ use Friendica\Util\Strings;
  */
 function notification($params)
 {
-	$a = \get_app();
+	$a = DI::app();
 
 	// Temporary logging for finding the origin
 	if (!isset($params['uid'])) {
diff --git a/mod/fbrowser.php b/mod/fbrowser.php
index 94d575c46f..2b293a716d 100644
--- a/mod/fbrowser.php
+++ b/mod/fbrowser.php
@@ -78,7 +78,7 @@ function fbrowser_content(App $a)
 
 			function _map_files1($rr)
 			{
-				$a = \get_app();
+				$a = DI::app();
 				$types = Images::supportedTypes();
 				$ext = $types[$rr['type']];
 				$filename_e = $rr['filename'];
diff --git a/mod/item.php b/mod/item.php
index d6ce4a0944..90d8f3eada 100644
--- a/mod/item.php
+++ b/mod/item.php
@@ -848,7 +848,7 @@ function item_post(App $a) {
 function item_post_return($baseurl, $api_source, $return_path)
 {
 	// figure out how to return, depending on from whence we came
-    $a = \get_app();
+    $a = DI::app();
 
 	if ($api_source) {
 		return;
diff --git a/mod/message.php b/mod/message.php
index 019ee61c9d..3d378f5158 100644
--- a/mod/message.php
+++ b/mod/message.php
@@ -499,7 +499,7 @@ function get_messages($uid, $start, $limit)
 
 function render_messages(array $msg, $t)
 {
-	$a = \get_app();
+	$a = DI::app();
 
 	$tpl = Renderer::getMarkupTemplate($t);
 	$rslt = '';
diff --git a/mod/settings.php b/mod/settings.php
index 4f13fc72fc..4f44e9a00e 100644
--- a/mod/settings.php
+++ b/mod/settings.php
@@ -33,7 +33,7 @@ function get_theme_config_file($theme)
 {
 	$theme = Strings::sanitizeFilePathItem($theme);
 
-	$a = \get_app();
+	$a = DI::app();
 	$base_theme = $a->theme_info['extends'] ?? '';
 
 	if (file_exists("view/theme/$theme/config.php")) {
diff --git a/src/BaseModule.php b/src/BaseModule.php
index dcacce78bb..61bfe8e8d3 100644
--- a/src/BaseModule.php
+++ b/src/BaseModule.php
@@ -88,7 +88,7 @@ abstract class BaseModule
 	 */
 	public static function getFormSecurityToken($typename = '')
 	{
-		$a = \get_app();
+		$a = DI::app();
 
 		$timestamp = time();
 		$sec_hash = hash('whirlpool', $a->user['guid'] . $a->user['prvkey'] . session_id() . $timestamp . $typename);
@@ -116,7 +116,7 @@ abstract class BaseModule
 
 		$max_livetime = 10800; // 3 hours
 
-		$a = \get_app();
+		$a = DI::app();
 
 		$x = explode('.', $hash);
 		if (time() > (intval($x[0]) + $max_livetime)) {
@@ -136,7 +136,7 @@ abstract class BaseModule
 	public static function checkFormSecurityTokenRedirectOnError($err_redirect, $typename = '', $formname = 'form_security_token')
 	{
 		if (!self::checkFormSecurityToken($typename, $formname)) {
-			$a = \get_app();
+			$a = DI::app();
 			Logger::log('checkFormSecurityToken failed: user ' . $a->user['guid'] . ' - form element ' . $typename);
 			Logger::log('checkFormSecurityToken failed: _REQUEST data: ' . print_r($_REQUEST, true), Logger::DATA);
 			notice(self::getFormSecurityStandardErrorMessage());
@@ -147,7 +147,7 @@ abstract class BaseModule
 	public static function checkFormSecurityTokenForbiddenOnError($typename = '', $formname = 'form_security_token')
 	{
 		if (!self::checkFormSecurityToken($typename, $formname)) {
-			$a = \get_app();
+			$a = DI::app();
 			Logger::log('checkFormSecurityToken failed: user ' . $a->user['guid'] . ' - form element ' . $typename);
 			Logger::log('checkFormSecurityToken failed: _REQUEST data: ' . print_r($_REQUEST, true), Logger::DATA);
 
diff --git a/src/Console/DocBloxErrorChecker.php b/src/Console/DocBloxErrorChecker.php
index 4393e99b18..88c08666ca 100644
--- a/src/Console/DocBloxErrorChecker.php
+++ b/src/Console/DocBloxErrorChecker.php
@@ -2,6 +2,8 @@
 
 namespace Friendica\Console;
 
+use Friendica\App;
+
 /**
  * When I installed docblox, I had the experience that it does not generate any output at all.
  * This script may be used to find that kind of problems with the documentation build process.
@@ -29,6 +31,16 @@ class DocBloxErrorChecker extends \Asika\SimpleConsole\Console
 
 	protected $helpOptions = ['h', 'help', '?'];
 
+	/** @var App */
+	private $app;
+
+	public function __construct(App $app, array $argv = null)
+	{
+		parent::__construct($argv);
+
+		$this->app = $app;
+	}
+
 	protected function getHelp()
 	{
 		$help = <<<HELP
@@ -59,7 +71,7 @@ HELP;
 			throw new \RuntimeException('DocBlox isn\'t available.');
 		}
 
-		$dir = \get_app()->getBasePath();
+		$dir = $this->app->getBasePath();
 
 		//stack for dirs to search
 		$dirstack = [];
diff --git a/src/Console/PhpToPo.php b/src/Console/PhpToPo.php
index d73c7f4ab6..b88ef023ea 100644
--- a/src/Console/PhpToPo.php
+++ b/src/Console/PhpToPo.php
@@ -2,6 +2,8 @@
 
 namespace Friendica\Console;
 
+use Friendica\App;
+
 /**
  * Read a strings.php file and create messages.po in the same directory
  *
@@ -15,6 +17,16 @@ class PhpToPo extends \Asika\SimpleConsole\Console
 	private $normBaseMsgIds = [];
 	const NORM_REGEXP = "|[\\\]|";
 
+	/** @var App */
+	private $app;
+
+	public function __construct(App $app, array $argv = null)
+	{
+		parent::__construct($argv);
+
+		$this->app = $app;
+	}
+
 	protected function getHelp()
 	{
 		$help = <<<HELP
@@ -51,7 +63,7 @@ HELP;
 			throw new \Asika\SimpleConsole\CommandArgsException('Too many arguments');
 		}
 
-		$a = \get_app();
+		$a = $this->app;
 
 		$phpfile = realpath($this->getArgument(0));
 
diff --git a/src/Content/OEmbed.php b/src/Content/OEmbed.php
index 42748d69ba..95fd6530b6 100644
--- a/src/Content/OEmbed.php
+++ b/src/Content/OEmbed.php
@@ -57,7 +57,7 @@ class OEmbed
 	{
 		$embedurl = trim($embedurl, '\'"');
 
-		$a = \get_app();
+		$a = DI::app();
 
 		$cache_key = 'oembed:' . $a->videowidth . ':' . $embedurl;
 
diff --git a/src/Content/Text/HTML.php b/src/Content/Text/HTML.php
index 8a54c26a7c..a25883eb16 100644
--- a/src/Content/Text/HTML.php
+++ b/src/Content/Text/HTML.php
@@ -12,6 +12,7 @@ use Friendica\Core\Hook;
 use Friendica\Core\L10n;
 use Friendica\Core\Config;
 use Friendica\Core\Renderer;
+use Friendica\DI;
 use Friendica\Model\Contact;
 use Friendica\Util\Network;
 use Friendica\Util\Proxy as ProxyUtils;
@@ -815,7 +816,7 @@ class HTML
 	 */
 	public static function contactBlock()
 	{
-		$a = \get_app();
+		$a = DI::app();
 
 		return ContactBlock::getHTML($a->profile);
 	}
diff --git a/src/Content/Widget.php b/src/Content/Widget.php
index f1f8f25fa3..8f88a0d836 100644
--- a/src/Content/Widget.php
+++ b/src/Content/Widget.php
@@ -302,7 +302,7 @@ class Widget
 	 */
 	public static function categories($baseurl, $selected = '')
 	{
-		$a = \get_app();
+		$a = DI::app();
 
 		$uid = intval($a->profile['profile_uid']);
 
@@ -420,7 +420,7 @@ class Widget
 	 */
 	public static function tagCloud($limit = 50)
 	{
-		$a = \get_app();
+		$a = DI::app();
 
 		$uid = intval($a->profile['profile_uid']);
 
diff --git a/src/Content/Widget/CalendarExport.php b/src/Content/Widget/CalendarExport.php
index c78ca21ebe..a6fea1e8a1 100644
--- a/src/Content/Widget/CalendarExport.php
+++ b/src/Content/Widget/CalendarExport.php
@@ -9,6 +9,7 @@ namespace Friendica\Content\Widget;
 use Friendica\Content\Feature;
 use Friendica\Core\L10n;
 use Friendica\Core\Renderer;
+use Friendica\DI;
 
 /**
  * TagCloud widget
@@ -24,7 +25,7 @@ class CalendarExport
 	 * @throws \Friendica\Network\HTTPException\InternalServerErrorException
 	 */
 	public static function getHTML() {
-		$a = \get_app();
+		$a = DI::app();
 
 		if (empty($a->data['user'])) {
 			return;
diff --git a/src/Core/Worker.php b/src/Core/Worker.php
index 02c8f65cbb..1eea922396 100644
--- a/src/Core/Worker.php
+++ b/src/Core/Worker.php
@@ -48,8 +48,6 @@ class Worker
 	 */
 	public static function processQueue($run_cron = true)
 	{
-		$a = \get_app();
-
 		// Ensure that all "strtotime" operations do run timezone independent
 		date_default_timezone_set('UTC');
 
@@ -372,7 +370,7 @@ class Worker
 	 */
 	private static function execFunction($queue, $funcname, $argv, $method_call)
 	{
-		$a = \get_app();
+		$a = DI::app();
 
 		$argc = count($argv);
 
@@ -1083,7 +1081,7 @@ class Worker
 
 		$args = ['no_cron' => !$do_cron];
 
-		$a = get_app();
+		$a = DI::app();
 		$process = new Core\Process(DI::logger(), DI::mode(), DI::config(), $a->getBasePath());
 		$process->run($command, $args);
 
diff --git a/src/Model/Contact.php b/src/Model/Contact.php
index 6cda8e404f..10cf4bf341 100644
--- a/src/Model/Contact.php
+++ b/src/Model/Contact.php
@@ -2220,7 +2220,7 @@ class Contact
 	{
 		$result = ['cid' => -1, 'success' => false, 'message' => ''];
 
-		$a = \get_app();
+		$a = DI::app();
 
 		// remove ajax junk, e.g. Twitter
 		$url = str_replace('/#!/', '/', $url);
diff --git a/src/Model/Mail.php b/src/Model/Mail.php
index ec333ed436..eeea130a60 100644
--- a/src/Model/Mail.php
+++ b/src/Model/Mail.php
@@ -105,7 +105,7 @@ class Mail
 	 */
 	public static function send($recipient = 0, $body = '', $subject = '', $replyto = '')
 	{
-		$a = \get_app();
+		$a = DI::app();
 
 		if (!$recipient) {
 			return -1;
diff --git a/src/Model/Photo.php b/src/Model/Photo.php
index eee8fbc5f7..c4dbf2b30a 100644
--- a/src/Model/Photo.php
+++ b/src/Model/Photo.php
@@ -461,7 +461,7 @@ class Photo
 			$micro = DI::baseUrl() . "/photo/" . $resource_id . "-6." . $Image->getExt() . $suffix;
 
 			// Remove the cached photo
-			$a = \get_app();
+			$a = DI::app();
 			$basepath = $a->getBasePath();
 
 			if (is_dir($basepath . "/photo")) {
diff --git a/src/Model/Profile.php b/src/Model/Profile.php
index 4bb886814d..d7cc906fdb 100644
--- a/src/Model/Profile.php
+++ b/src/Model/Profile.php
@@ -568,7 +568,7 @@ class Profile
 
 	public static function getBirthdays()
 	{
-		$a = \get_app();
+		$a = DI::app();
 		$o = '';
 
 		if (!local_user() || DI::mode()->isMobile() || DI::mode()->isMobile()) {
@@ -665,7 +665,7 @@ class Profile
 
 	public static function getEventsReminderHTML()
 	{
-		$a = \get_app();
+		$a = DI::app();
 		$o = '';
 
 		if (!local_user() || DI::mode()->isMobile() || DI::mode()->isMobile()) {
@@ -1106,7 +1106,7 @@ class Profile
 	 */
 	public static function addVisitorCookieForHandle($handle)
 	{
-		$a = \get_app();
+		$a = DI::app();
 
 		// Try to find the public contact entry of the visitor.
 		$cid = Contact::getIdForURL($handle);
@@ -1144,7 +1144,7 @@ class Profile
 	 */
 	public static function openWebAuthInit($token)
 	{
-		$a = \get_app();
+		$a = DI::app();
 
 		// Clean old OpenWebAuthToken entries.
 		OpenWebAuthToken::purge('owt', '3 MINUTE');
diff --git a/src/Protocol/DFRN.php b/src/Protocol/DFRN.php
index 354653c9b9..798f607927 100644
--- a/src/Protocol/DFRN.php
+++ b/src/Protocol/DFRN.php
@@ -146,7 +146,7 @@ class DFRN
 	 */
 	public static function feed($dfrn_id, $owner_nick, $last_update, $direction = 0, $onlyheader = false)
 	{
-		$a = \get_app();
+		$a = DI::app();
 
 		$sitefeed    = ((strlen($owner_nick)) ? false : true); // not yet implemented, need to rewrite huge chunks of following logic
 		$public_feed = (($dfrn_id) ? false : true);
diff --git a/src/Render/FriendicaSmarty.php b/src/Render/FriendicaSmarty.php
index deabd3baf2..83b6322df2 100644
--- a/src/Render/FriendicaSmarty.php
+++ b/src/Render/FriendicaSmarty.php
@@ -4,6 +4,7 @@
  */
 namespace Friendica\Render;
 
+use Friendica\DI;
 use Smarty;
 use Friendica\Core\Renderer;
 
@@ -22,7 +23,7 @@ class FriendicaSmarty extends Smarty
 	{
 		parent::__construct();
 
-		$a = \get_app();
+		$a = DI::app();
 		$theme = $a->getCurrentTheme();
 
 		// setTemplateDir can be set to an array, which Smarty will parse in order.
diff --git a/src/Render/FriendicaSmartyEngine.php b/src/Render/FriendicaSmartyEngine.php
index 36e46435fe..d36b8f1958 100644
--- a/src/Render/FriendicaSmartyEngine.php
+++ b/src/Render/FriendicaSmartyEngine.php
@@ -5,6 +5,7 @@
 namespace Friendica\Render;
 
 use Friendica\Core\Hook;
+use Friendica\DI;
 
 /**
  * Smarty implementation of the Friendica template engine interface
@@ -32,7 +33,7 @@ class FriendicaSmartyEngine implements ITemplateEngine
 			$s = new FriendicaSmarty();
 		}
 
-		$r['$APP'] = \get_app();
+		$r['$APP'] = DI::app();
 
 		// "middleware": inject variables into templates
 		$arr = [
@@ -54,7 +55,7 @@ class FriendicaSmartyEngine implements ITemplateEngine
 
 	public function getTemplateFile($file, $root = '')
 	{
-		$a = \get_app();
+		$a = DI::app();
 		$template = new FriendicaSmarty();
 
 		// Make sure $root ends with a slash /
diff --git a/src/Util/Network.php b/src/Util/Network.php
index 1f16d9a724..0f6389ce87 100644
--- a/src/Util/Network.php
+++ b/src/Util/Network.php
@@ -96,7 +96,7 @@ class Network
 	{
 		$stamp1 = microtime(true);
 
-		$a = \get_app();
+		$a = DI::app();
 
 		if (strlen($url) > 1000) {
 			Logger::log('URL is longer than 1000 characters. Callstack: ' . System::callstack(20), Logger::DEBUG);
@@ -260,7 +260,7 @@ class Network
 			return CurlResult::createErrorCurl($url);
 		}
 
-		$a = \get_app();
+		$a = DI::app();
 		$ch = curl_init($url);
 
 		if (($redirects > 8) || (!$ch)) {
@@ -630,7 +630,7 @@ class Network
 	 */
 	public static function finalUrl(string $url, int $depth = 1, bool $fetchbody = false)
 	{
-		$a = \get_app();
+		$a = DI::app();
 
 		$url = self::stripTrackingQueryParams($url);
 
diff --git a/tests/include/ApiTest.php b/tests/include/ApiTest.php
index 6a5dde0c65..58e0adb99a 100644
--- a/tests/include/ApiTest.php
+++ b/tests/include/ApiTest.php
@@ -1383,7 +1383,7 @@ class ApiTest extends DatabaseTest
 				'type'     => 'image/png'
 			]
 		];
-		$app       = \get_app();
+		$app       = DI::app();
 		$app->argc = 2;
 
 		$result = api_media_upload();
diff --git a/view/theme/frio/php/scheme.php b/view/theme/frio/php/scheme.php
index fa933bd941..b2b346cccb 100644
--- a/view/theme/frio/php/scheme.php
+++ b/view/theme/frio/php/scheme.php
@@ -19,11 +19,12 @@
  */
 
 use Friendica\Core\PConfig;
+use Friendica\DI;
 use Friendica\Util\Strings;
 
 function get_scheme_info($scheme)
 {
-	$theme = \get_app()->getCurrentTheme();
+	$theme = DI::app()->getCurrentTheme();
 	$themepath = 'view/theme/' . $theme . '/';
 	if (empty($scheme)) {
 		$scheme = PConfig::get(local_user(), 'frio', 'scheme', PConfig::get(local_user(), 'frio', 'schema'));
diff --git a/view/theme/vier/theme.php b/view/theme/vier/theme.php
index 98e8b68078..2a4abdfbea 100644
--- a/view/theme/vier/theme.php
+++ b/view/theme/vier/theme.php
@@ -106,7 +106,7 @@ function get_vier_config($key, $default = false, $admin = false)
 
 function vier_community_info()
 {
-	$a = \get_app();
+	$a = DI::app();
 
 	$show_pages      = get_vier_config("show_pages", 1);
 	$show_profiles   = get_vier_config("show_profiles", 1);

From 244f440d97436e92836a95b207fb6737c12c9d0d Mon Sep 17 00:00:00 2001
From: nupplaPhil <admin@philipp.info>
Date: Sat, 4 Jan 2020 23:43:13 +0100
Subject: [PATCH 11/11] Remove unused killme()

---
 boot.php                  | 9 ---------
 mod/photos.php            | 2 +-
 src/Core/System.php       | 1 -
 tests/include/ApiTest.php | 4 ++--
 4 files changed, 3 insertions(+), 13 deletions(-)

diff --git a/boot.php b/boot.php
index d54ee72a3d..f36e770da1 100644
--- a/boot.php
+++ b/boot.php
@@ -234,15 +234,6 @@ if (!defined('CURLE_OPERATION_TIMEDOUT')) {
 	define('CURLE_OPERATION_TIMEDOUT', CURLE_OPERATION_TIMEOUTED);
 }
 
-/**
- * @brief Used to end the current process, after saving session state.
- * @deprecated
- */
-function killme()
-{
-	exit();
-}
-
 /**
  * @brief Returns the user id of locally logged in user or false.
  *
diff --git a/mod/photos.php b/mod/photos.php
index e763704c40..2ca6c6a37b 100644
--- a/mod/photos.php
+++ b/mod/photos.php
@@ -814,7 +814,7 @@ function photos_post(App $a)
 
 	Hook::callAll('photo_post_end', $item_id);
 
-	// addon uploaders should call "killme()" [e.g. exit] within the photo_post_end hook
+	// addon uploaders should call "exit()" within the photo_post_end hook
 	// if they do not wish to be redirected
 
 	DI::baseUrl()->redirect($_SESSION['photo_return']);
diff --git a/src/Core/System.php b/src/Core/System.php
index 709864492e..63767ebb34 100644
--- a/src/Core/System.php
+++ b/src/Core/System.php
@@ -283,7 +283,6 @@ class System
 
 	/// @todo Move the following functions from boot.php
 	/*
-	function killme()
 	function local_user()
 	function public_contact()
 	function remote_user()
diff --git a/tests/include/ApiTest.php b/tests/include/ApiTest.php
index 58e0adb99a..f702d70bca 100644
--- a/tests/include/ApiTest.php
+++ b/tests/include/ApiTest.php
@@ -3305,7 +3305,7 @@ class ApiTest extends DatabaseTest
 	 */
 	public function testApiOauthRequestToken()
 	{
-		$this->markTestIncomplete('killme() kills phpunit as well');
+		$this->markTestIncomplete('exit() kills phpunit as well');
 	}
 
 	/**
@@ -3315,7 +3315,7 @@ class ApiTest extends DatabaseTest
 	 */
 	public function testApiOauthAccessToken()
 	{
-		$this->markTestIncomplete('killme() kills phpunit as well');
+		$this->markTestIncomplete('exit() kills phpunit as well');
 	}
 
 	/**